]> andersk Git - splint.git/blob - src/sRef.c
Runs on test suite wu-ftpd and bind without crashing or producing obvious errors.
[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 /*
2043   drl add 12/24/2000
2044   s is an sRef of a formal paramenter in a function call constraint
2045   we trys to return a constraint expression derived from the actual parementer of a function call.
2046 */
2047 /*@only@*/ constraintExpr sRef_fixConstraintParam (/*@observer@*/  sRef s, /*@observer@*/ /*@temp@*/ exprNodeList args)
2048 {
2049   constraintExpr ce;
2050
2051   if (sRef_isInvalid (s))
2052     llfatalbug((message("Invalid sRef")));
2053
2054   switch (s->kind)
2055     {
2056     case SK_RESULT:
2057       {
2058         //      s = sRef_saveCopy(s);
2059         ce = constraintExpr_makeTermsRef (s);
2060         return ce;
2061       }
2062     case SK_FIELD:
2063       {
2064         sRef temp;
2065         
2066         temp = (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2067                               s->info->field->field));
2068         ce = constraintExpr_makeTermsRef (temp);
2069         return ce;
2070       }
2071     case SK_PTR:
2072       {
2073         sRef temp;
2074         temp = (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2075         //temp = sRef_saveCopy(temp);
2076         ce = constraintExpr_makeTermsRef (temp);
2077         return ce;
2078       }
2079
2080     case SK_ARRAYFETCH:
2081        {
2082         sRef temp;
2083         temp = sRef_saveCopy(s);
2084         temp = sRef_fixBaseParam (temp, args);
2085         ce = constraintExpr_makeTermsRef (temp);
2086         return ce;
2087       }
2088     case SK_CVAR:
2089       {
2090         sRef temp;
2091         temp = sRef_saveCopy(s);
2092         ce = constraintExpr_makeTermsRef (temp);
2093         return ce;
2094       }
2095     case SK_PARAM:
2096       llassert(exprNodeList_size (args) > s->info->paramno);
2097         {
2098           exprNode e = exprNodeList_nth (args, s->info->paramno);
2099
2100           llassert( !(exprNode_isError (e)) );
2101           ce = constraintExpr_makeExprNode (e);
2102           return ce;
2103         }
2104
2105     default:
2106       {
2107         sRef temp;
2108       llcontbug ((message("Trying to do fixConstraintParam on nonparam, nonglobal: %q for function with arguments %q", sRef_unparse (s), exprNodeList_unparse(args) ) ));
2109       temp = sRef_saveCopy(s);
2110       ce = constraintExpr_makeTermsRef (temp);
2111       return ce;
2112       }
2113     }
2114
2115   
2116
2117 }
2118
2119 /*@exposed@*/ sRef
2120 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
2121 {
2122   if (sRef_isInvalid (s)) return (sRef_undefined);
2123
2124   switch (s->kind)
2125     {
2126     case SK_UNCONSTRAINED:
2127     case SK_CVAR:
2128       return s;
2129     case SK_PARAM:
2130       {
2131         if (exprNodeList_size (args) > s->info->paramno)
2132           {
2133             exprNode e = exprNodeList_nth (args, s->info->paramno);
2134
2135             if (exprNode_isError (e))
2136               {
2137                 return sRef_makeUnknown ();
2138               }
2139             
2140             return (exprNode_getSref (e));
2141           }
2142         else
2143           {
2144             return sRef_makeUnknown ();
2145           }
2146       }
2147     case SK_ARRAYFETCH:
2148
2149       if (s->info->arrayfetch->indknown)
2150         {
2151           return (sRef_makeArrayFetchKnown 
2152                   (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
2153                    s->info->arrayfetch->ind));
2154         }
2155       else
2156         {
2157           return (sRef_makeArrayFetch 
2158                   (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
2159         }
2160     case SK_FIELD:
2161       return (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
2162                               s->info->field->field));
2163
2164     case SK_PTR:
2165       return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
2166
2167     case SK_ADR:
2168       return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
2169
2170     case SK_CONJ:
2171       return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
2172                              sRef_fixBaseParam (s->info->conj->b, args)));
2173     case SK_DERIVED:
2174     case SK_SPECIAL:
2175     case SK_TYPE:
2176     case SK_CONST:
2177     case SK_NEW:
2178     case SK_UNKNOWN:
2179     case SK_OBJECT:
2180     case SK_EXTERNAL:
2181     case SK_RESULT:
2182       return s;
2183     }
2184   BADEXIT;
2185 }
2186
2187 /*@exposed@*/ sRef
2188 sRef_undumpGlobal (char **c)
2189 {
2190   char p = **c;
2191
2192   (*c)++;
2193
2194   switch (p)
2195     {
2196     case 'g':
2197       {
2198         usymId uid = usymId_fromInt (getInt (c));
2199         sstate defstate;
2200         nstate nullstate;
2201         sRef ret;
2202
2203         checkChar (c, '@');
2204         defstate = sstate_fromInt (getInt (c));
2205
2206         checkChar (c, '@');
2207         nullstate = nstate_fromInt (getInt (c));
2208
2209         ret = sRef_makeGlobal (uid, ctype_unknown);
2210         ret->nullstate = nullstate;
2211         ret->defstate = defstate;
2212         return ret;
2213       }
2214     case 's':
2215       {
2216         int i = getInt (c);
2217         speckind sk = speckind_fromInt (i);
2218
2219         switch (sk)
2220           {
2221           case SR_NOTHING:   return (sRef_makeNothing ());
2222           case SR_INTERNAL:  return (sRef_makeInternalState ());
2223           case SR_SPECSTATE: return (sRef_makeSpecState ());
2224           case SR_SYSTEM:    return (sRef_makeSystemState ());
2225           }
2226         BADEXIT;
2227       }
2228     case '-':
2229       return sRef_undefined;
2230     case 'u':
2231       return sRef_makeUnknown ();
2232     case 'x':
2233       return sRef_makeUnknown ();
2234     default:
2235       llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
2236                              cstring_fromChars (*c)));
2237     }
2238   BADEXIT;
2239 }
2240
2241 /*@exposed@*/ sRef
2242 sRef_undump (char **c)
2243 {
2244   char p = **c;
2245
2246   (*c)++;
2247
2248   switch (p)
2249     {
2250     case 'g':
2251       return (sRef_makeGlobal (usymId_fromInt (getInt (c)), ctype_unknown));
2252     case 'p':
2253       return (sRef_makeParam (getInt (c), ctype_unknown));
2254     case 'r':
2255       return (sRef_makeResultType (ctype_undump (c)));
2256     case 'a':
2257       {
2258         if ((**c >= '0' && **c <= '9') || **c == '-')
2259           {
2260             int i = getInt (c);
2261             sRef arr = sRef_undump (c);
2262             sRef ret = sRef_buildArrayFetchKnown (arr, i);
2263
2264             return ret;
2265           }
2266         else
2267           {
2268             sRef arr = sRef_undump (c);
2269             sRef ret = sRef_buildArrayFetch (arr);
2270
2271             return ret;
2272           }
2273       }
2274     case 'f':
2275       {
2276         cstring fname = cstring_undefined;
2277         sRef ret;
2278
2279         while (**c != '.')
2280           {
2281             fname = cstring_appendChar (fname, **c);
2282             (*c)++;
2283           }
2284         (*c)++;
2285
2286         ret = sRef_buildField (sRef_undump (c), fname);
2287         cstring_markOwned (fname);
2288         return (ret);
2289       }
2290     case 's':
2291       {
2292         int i = getInt (c);
2293         speckind sk = speckind_fromInt (i);
2294
2295         switch (sk)
2296           {
2297           case SR_NOTHING:   return (sRef_makeNothing ());
2298           case SR_INTERNAL:  return (sRef_makeInternalState ());
2299           case SR_SPECSTATE: return (sRef_makeSpecState ());
2300           case SR_SYSTEM:    return (sRef_makeSystemState ());
2301           }
2302         BADEXIT;
2303       }
2304     case 't':
2305       {
2306         sRef ptr = sRef_undump (c);
2307         sRef ret = sRef_makePointer (ptr);
2308
2309         return (ret);
2310       }
2311     case 'd':
2312       {
2313         sRef adr = sRef_undump (c);
2314         sRef ret = sRef_makeAddress (adr);
2315
2316         return (ret);
2317       }
2318     case 'o':
2319       {
2320         return (sRef_makeObject (ctype_undump (c)));
2321       }
2322     case 'c':
2323       {
2324         sRef s1 = sRef_undump (c);
2325         sRef s2 = ((*c)++, sRef_undump (c));
2326         sRef ret = sRef_makeConj (s1, s2);
2327
2328         return (ret);
2329       }
2330     case '-':
2331       return sRef_undefined;
2332     case 'u':
2333       return sRef_makeUnknown ();
2334     case 'x':
2335       return sRef_makeUnknown ();
2336     default:
2337       llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
2338     }
2339   BADEXIT;
2340 }
2341
2342 /*@only@*/ cstring
2343 sRef_dump (sRef s)
2344 {
2345   if (sRef_isInvalid (s))
2346     {
2347       return (cstring_makeLiteral ("-"));
2348     }
2349   else
2350     {
2351       switch (s->kind)
2352         {
2353         case SK_PARAM:
2354           return (message ("p%d", s->info->paramno));
2355         case SK_ARRAYFETCH:
2356           if (s->info->arrayfetch->indknown)
2357             {
2358               return (message ("a%d%q", s->info->arrayfetch->ind,
2359                                sRef_dump (s->info->arrayfetch->arr)));
2360             }
2361           else
2362             {
2363               return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
2364             }
2365         case SK_FIELD:
2366           return (message ("f%s.%q", s->info->field->field, 
2367                            sRef_dump (s->info->field->rec)));
2368         case SK_PTR:
2369           return (message ("t%q", sRef_dump (s->info->ref)));
2370         case SK_ADR:
2371           return (message ("d%q", sRef_dump (s->info->ref)));
2372         case SK_OBJECT:
2373           return (message ("o%q", ctype_dump (s->info->object)));
2374         case SK_SPECIAL:
2375           return (message ("s%d", (int) s->info->spec));
2376         case SK_CONJ:
2377           return (message ("c%q.%q",
2378                            sRef_dump (s->info->conj->a),
2379                            sRef_dump (s->info->conj->b)));
2380         case SK_CVAR:
2381           if (sRef_isGlobal (s))
2382             {
2383               return (message ("g%d", 
2384                                usymtab_convertId (s->info->cvar->index)));
2385             }
2386           else
2387             {
2388               llcontbug (message ("Dumping local variable: %q",
2389                                   sRef_unparseDebug (s)));
2390               return (cstring_makeLiteral ("u"));
2391             }
2392         case SK_UNKNOWN:
2393           return (cstring_makeLiteral ("u"));
2394         case SK_RESULT:
2395           return (message ("r%q", ctype_dump (s->type)));
2396         case SK_TYPE:
2397         case SK_CONST:
2398         case SK_EXTERNAL:
2399         case SK_DERIVED:
2400         case SK_NEW:
2401         case SK_UNCONSTRAINED:
2402           llcontbug (message ("sRef_dump: bad kind: %q",
2403                               sRef_unparseFull (s)));
2404           return (cstring_makeLiteral ("x"));
2405         }
2406     }
2407      
2408   BADEXIT;
2409 }
2410
2411 cstring sRef_dumpGlobal (sRef s)
2412 {
2413   if (sRef_isInvalid (s))
2414     {
2415       return (cstring_makeLiteral ("-"));
2416     }
2417   else
2418     {
2419       switch (s->kind)
2420         {
2421         case SK_CVAR:
2422           if (sRef_isGlobal (s))
2423             {
2424               return (message ("g%d@%d@%d", 
2425                                usymtab_convertId (s->info->cvar->index),
2426                                (int) s->defstate,
2427                                (int) s->nullstate));
2428             }
2429           else
2430             {
2431               llcontbug (message ("Dumping local variable: %q",
2432                                   sRef_unparseDebug (s)));
2433               return (cstring_makeLiteral ("u"));
2434             }
2435         case SK_UNKNOWN:
2436           return (cstring_makeLiteral ("u"));
2437         case SK_SPECIAL:
2438           return (message ("s%d", (int) s->info->spec));
2439         default:
2440           llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
2441                               sRef_unparseFull (s)));
2442           return (cstring_makeLiteral ("x"));
2443         }
2444     }
2445      
2446   BADEXIT;
2447 }
2448
2449 ctype
2450 sRef_deriveType (sRef s, uentryList cl)
2451 {
2452   if (sRef_isInvalid (s)) return ctype_unknown;
2453
2454   switch (s->kind)
2455     {
2456     case SK_CVAR:
2457       return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel, 
2458                                               s->info->cvar->index)));
2459     case SK_UNCONSTRAINED:
2460       return (ctype_unknown);
2461     case SK_PARAM:
2462       return uentry_getType (uentryList_getN (cl, s->info->paramno));
2463     case SK_ARRAYFETCH:
2464       {
2465         ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
2466         
2467         if (ctype_isArray (ca))
2468           {
2469             return (ctype_baseArrayPtr (ca));
2470           }
2471         else if (ctype_isUnknown (ca))
2472           {
2473             return (ca);
2474           }
2475         else
2476           {
2477             llcontbuglit ("sRef_deriveType: inconsistent array type");
2478             return ca;
2479           }
2480       }
2481     case SK_FIELD:
2482       {
2483         ctype ct = sRef_deriveType (s->info->field->rec, cl);
2484         
2485         if (ctype_isStructorUnion (ct))
2486           {
2487             uentry ue = uentryList_lookupField (ctype_getFields (ct), 
2488                                                s->info->field->field);
2489             
2490             if (uentry_isValid (ue))
2491               {
2492                 return (uentry_getType (ue));
2493               }
2494             else
2495               {
2496                 llcontbuglit ("sRef_deriveType: bad field");
2497                 return ctype_unknown;
2498               }
2499           }
2500         else if (ctype_isUnknown (ct))
2501           {
2502             return (ct);
2503           }
2504         else
2505           {
2506             llcontbuglit ("sRef_deriveType: inconsistent field type");
2507             return (ct);
2508           }
2509       }
2510     case SK_PTR:
2511       {
2512         ctype ct = sRef_deriveType (s->info->ref, cl);
2513         
2514         if (ctype_isUnknown (ct)) return ct;
2515         if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
2516         else
2517           {
2518             llcontbuglit ("sRef_deriveType: inconsistent pointer type");
2519             return (ct);
2520           }
2521       }
2522     case SK_ADR:
2523       {
2524         ctype ct = sRef_deriveType (s->info->ref, cl);
2525         
2526         if (ctype_isUnknown (ct)) return ct;
2527         return ctype_makePointer (ct);
2528       }
2529     case SK_DERIVED:
2530       {
2531         return sRef_deriveType (s->info->ref, cl);
2532       }
2533     case SK_OBJECT:
2534       {
2535         return (s->info->object);
2536       }
2537     case SK_CONJ:
2538       {
2539         return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
2540                                sRef_deriveType (s->info->conj->b, cl)));
2541       }
2542     case SK_RESULT:
2543     case SK_CONST:
2544     case SK_TYPE:
2545       {
2546         return (s->type);
2547       }
2548     case SK_SPECIAL:
2549     case SK_UNKNOWN:
2550     case SK_EXTERNAL:
2551     case SK_NEW:
2552       return ctype_unknown;
2553     }
2554   BADEXIT;
2555 }
2556
2557 ctype
2558 sRef_getType (sRef s)
2559 {
2560   if (sRef_isInvalid (s)) return ctype_unknown;
2561   return s->type;
2562 }
2563
2564
2565 /*@only@*/ cstring
2566 sRef_unparseOpt (sRef s)
2567 {
2568   sRef rb = sRef_getRootBase (s);
2569
2570   if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2571     {
2572       cstring ret = sRef_unparse (s);
2573       
2574       llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2575
2576       if (!cstring_isEmpty (ret))
2577         {
2578           return (cstring_appendChar (ret, ' '));
2579         }
2580       else
2581         {
2582           return ret;
2583         }
2584     }
2585
2586   return cstring_undefined;
2587 }
2588
2589 cstring
2590 sRef_unparsePreOpt (sRef s)
2591 {
2592   sRef rb = sRef_getRootBase (s);
2593
2594   if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
2595     {
2596       cstring ret = sRef_unparse (s);
2597       
2598       llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
2599       return (cstring_prependCharO (' ', ret));
2600     }
2601
2602   return cstring_undefined;
2603 }
2604
2605 /*@only@*/ cstring
2606 sRef_unparse (sRef s)
2607 {
2608   if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2609
2610   if (context_inFunctionLike ())
2611     {
2612       return (sRef_unparseWithArgs (s, context_getParams ()));
2613     }
2614   else
2615     {
2616       return (sRef_unparseNoArgs (s));
2617     }
2618 }
2619
2620 static /*@only@*/ cstring
2621 sRef_unparseWithArgs (sRef s, uentryList args)
2622 {
2623   if (sRef_isInvalid (s))
2624     {
2625       return (cstring_makeLiteral ("?"));
2626     }
2627
2628   switch (s->kind)
2629     {
2630     case SK_CVAR:
2631       return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
2632                                                    s->info->cvar->index)));
2633     case SK_UNCONSTRAINED:
2634       return (cstring_copy (s->info->fname));
2635     case SK_PARAM:
2636       {
2637         if (s->info->paramno < uentryList_size (args))
2638           {
2639             uentry ue = uentryList_getN (args, s->info->paramno);
2640             
2641             if (uentry_isValid (ue))
2642               return uentry_getName (ue);
2643           }
2644
2645         return (message ("<bad param: %q / args %q",
2646                          sRef_unparseDebug (s),
2647                          uentryList_unparse (args)));
2648       }
2649     case SK_ARRAYFETCH:
2650       if (s->info->arrayfetch->indknown)
2651         {
2652           return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
2653                                 s->info->arrayfetch->ind));
2654         }
2655       else
2656         {
2657           return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
2658         }
2659     case SK_FIELD:
2660       if (s->info->field->rec->kind == SK_PTR)
2661         {
2662           sRef ptr = s->info->field->rec;
2663
2664           return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
2665                            s->info->field->field));       
2666         }
2667       return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
2668                        s->info->field->field));
2669
2670     case SK_PTR:
2671       {
2672         sRef ref = sRef_fixConj (s->info->ref);
2673         skind sk = ref->kind;
2674         cstring ret;
2675
2676         if (sk == SK_NEW)
2677           {
2678             ret = message ("storage pointed to by %q",
2679                            sRef_unparseWithArgs (ref, args));
2680           }
2681         else if (skind_isSimple (sk) || sk == SK_PTR)
2682           {
2683             ret = message ("*%q", sRef_unparseWithArgs (ref, args));
2684           }
2685         else
2686           {
2687             ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
2688           }
2689
2690         return ret;
2691       }
2692     case SK_ADR:
2693       return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
2694     case SK_OBJECT:
2695       return (cstring_copy (ctype_unparse (s->info->object)));
2696     case SK_CONJ:
2697       return (sRef_unparseWithArgs (sRef_getConjA (s), args));
2698     case SK_NEW:
2699       if (cstring_isDefined (s->info->fname))
2700         {
2701           return (message ("[result of %s]", s->info->fname));
2702         }
2703       else
2704         {
2705           return (cstring_makeLiteral ("<new>"));
2706         }
2707     case SK_UNKNOWN:
2708       return (cstring_makeLiteral ("?"));
2709     case SK_DERIVED:
2710       return (message ("<derived %q>", sRef_unparse (s->info->ref)));
2711     case SK_EXTERNAL:
2712       return (message ("<external %q>", sRef_unparse (s->info->ref)));
2713     case SK_TYPE:
2714       return (message ("<type %s>", ctype_unparse (s->type)));
2715     case SK_CONST:
2716       return (message ("<const %s>", ctype_unparse (s->type)));
2717     case SK_SPECIAL:
2718       return (cstring_makeLiteral
2719               (s->info->spec == SR_NOTHING ? "nothing"
2720                : s->info->spec == SR_INTERNAL ? "internal state"
2721                : s->info->spec == SR_SPECSTATE ? "spec state"
2722                : s->info->spec == SR_SYSTEM ? "file system state"
2723                : "<spec error>"));
2724     case SK_RESULT:
2725       return cstring_makeLiteral ("result");
2726     default:
2727       {
2728         llbug (message ("Bad sref, kind = %d", (int) s->kind));
2729       }
2730     }
2731
2732   BADEXIT;
2733 }
2734
2735 /*@only@*/ cstring
2736 sRef_unparseDebug (sRef s)
2737 {
2738   if (sRef_isInvalid (s)) return (cstring_makeLiteral ("<undef>"));
2739
2740   switch (s->kind)
2741     {
2742     case SK_UNCONSTRAINED:
2743       return (message ("<unconstrained %s>", s->info->fname));
2744     case SK_CVAR:
2745       {
2746         uentry ce;
2747
2748         ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
2749
2750         if (uentry_isInvalid (ce))
2751           {
2752             return (message ("<scope: %d.%d *invalid*>", 
2753                              s->info->cvar->lexlevel,
2754                              s->info->cvar->index));
2755           }
2756         else
2757           {
2758             return (message ("<scope: %d.%d *%q*>", 
2759                              s->info->cvar->lexlevel,
2760                              s->info->cvar->index,
2761                              uentry_getName (ce)));
2762           }
2763
2764       }
2765     case SK_PARAM:
2766       {
2767         return (message ("<parameter %d>", s->info->paramno + 1));
2768       }
2769     case SK_ARRAYFETCH:
2770       if (s->info->arrayfetch->indknown)
2771         {
2772           return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
2773                            s->info->arrayfetch->ind));
2774         }
2775       else
2776         {
2777           return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
2778         }
2779     case SK_FIELD:
2780       return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
2781                        s->info->field->field));
2782     case SK_PTR:
2783       return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
2784     case SK_ADR:
2785       return (message ("&%q", sRef_unparseDebug (s->info->ref)));
2786     case SK_OBJECT:
2787       return (message ("<object type %s>", ctype_unparse (s->info->object)));
2788     case SK_CONJ:
2789       return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
2790                        sRef_unparseDebug (s->info->conj->b)));
2791     case SK_NEW:
2792       return message ("<new: %s>", s->info->fname);
2793     case SK_DERIVED:
2794       return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
2795     case SK_EXTERNAL:
2796       return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
2797     case SK_TYPE:
2798       return (message ("<type %s>", ctype_unparse (s->type)));
2799     case SK_CONST:
2800       return (message ("<const %s>", ctype_unparse (s->type)));
2801     case SK_RESULT:
2802       return (message ("<result %s>", ctype_unparse (s->type)));
2803     case SK_SPECIAL:
2804       return (message ("<spec %s>",
2805                        cstring_makeLiteralTemp
2806                        (s->info->spec == SR_NOTHING ? "nothing"
2807                         : s->info->spec == SR_INTERNAL ? "internalState"
2808                         : s->info->spec == SR_SPECSTATE ? "spec state"
2809                         : s->info->spec == SR_SYSTEM ? "fileSystem"
2810                         : "error")));
2811     case SK_UNKNOWN:
2812       return cstring_makeLiteral ("<unknown>");
2813     }
2814
2815   BADEXIT;
2816 }
2817
2818 static /*@only@*/ cstring
2819 sRef_unparseNoArgs (sRef s)
2820 {
2821   if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
2822
2823   switch (s->kind)
2824     {
2825     case SK_UNCONSTRAINED:
2826       return (cstring_copy (s->info->fname));
2827     case SK_CVAR:
2828       {
2829         uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, 
2830                                          s->info->cvar->index);
2831
2832         if (uentry_isInvalid (ce))
2833           {
2834             llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q", sRef_unparseDebug (s)));
2835             return (sRef_unparseDebug (s)); 
2836           }
2837         else
2838           {
2839             return (uentry_getName (ce));
2840           }
2841       }
2842     case SK_ARRAYFETCH:
2843       if (s->info->arrayfetch->indknown)
2844         {
2845           return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
2846                            s->info->arrayfetch->ind));
2847         }
2848       else
2849         {
2850           return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
2851         }
2852     case SK_FIELD:
2853       return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
2854                        s->info->field->field));
2855     case SK_PTR:
2856       {
2857         sRef ref = sRef_fixConj (s->info->ref);
2858         skind sk = ref->kind;
2859         cstring ret;
2860
2861         if (skind_isSimple (sk) || sk == SK_PTR)
2862           {
2863             ret = message ("*%q", sRef_unparseNoArgs (ref));
2864           }
2865         else
2866           {
2867             ret = message ("*(%q)", sRef_unparseNoArgs (ref));
2868           }
2869
2870         return (ret);
2871       }
2872     case SK_ADR:
2873       return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
2874     case SK_OBJECT:
2875       return (cstring_copy (ctype_unparse (s->info->object)));
2876     case SK_CONJ:
2877       return (sRef_unparseNoArgs (s->info->conj->a));
2878     case SK_NEW:
2879       return (message ("result of %s", s->info->fname));
2880     case SK_DERIVED:
2881       return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
2882     case SK_EXTERNAL:
2883       return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
2884     case SK_SPECIAL:
2885       return (cstring_makeLiteral
2886               (s->info->spec == SR_NOTHING ? "nothing"
2887                : s->info->spec == SR_INTERNAL ? "internal state"
2888                : s->info->spec == SR_SPECSTATE ? "spec state"
2889                : s->info->spec == SR_SYSTEM ? "file system state"
2890                : "<spec error>"));
2891     case SK_RESULT:
2892       return cstring_makeLiteral ("result");
2893     case SK_CONST:
2894     case SK_TYPE:
2895     case SK_UNKNOWN:
2896       return cstring_makeLiteral ("?");
2897     case SK_PARAM:
2898       /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
2899       return (sRef_unparseDebug (s));
2900     }
2901   BADEXIT;
2902 }
2903
2904 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
2905 {
2906   sRef s = sRef_new ();
2907
2908   s->kind = SK_UNCONSTRAINED;
2909   s->info = (sinfo) dmalloc (sizeof (*s->info));
2910   s->info->fname = fname;
2911
2912   return (s);
2913 }
2914
2915 cstring sRef_unconstrainedName (sRef s)
2916 {
2917   llassert (sRef_isUnconstrained (s));
2918
2919   return s->info->fname;
2920 }
2921
2922 bool sRef_isUnconstrained (sRef s) 
2923 {
2924   return (sRef_isValid(s) && s->kind == SK_UNCONSTRAINED);
2925 }
2926
2927 static /*@dependent@*/ /*@notnull@*/ sRef 
2928   sRef_makeCvarAux (int level, usymId index, ctype ct)
2929 {
2930   sRef s = sRef_new ();
2931
2932     s->kind = SK_CVAR;
2933   s->info = (sinfo) dmalloc (sizeof (*s->info));
2934
2935   s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
2936   s->info->cvar->lexlevel = level;
2937   s->info->cvar->index = index;
2938
2939   /* for now, all globals are defined; all locals, aren't */
2940
2941   if (level <= fileScope)
2942     {
2943       s->defstate = SS_UNKNOWN;
2944     }
2945   else 
2946     {
2947       ctype rct = ctype_realType (ct);
2948
2949       if (level != paramsScope
2950           && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
2951         {
2952           s->defstate = SS_ALLOCATED; 
2953           s->oaliaskind = s->aliaskind = AK_STACK;
2954         }
2955       else
2956         {
2957           s->defstate = SS_UNDEFINED;
2958           s->oaliaskind = s->aliaskind = AK_LOCAL;
2959         }
2960     }
2961
2962   s->type = ct;
2963
2964   llassert (level >= globScope);
2965   llassert (usymId_isValid (index));
2966
2967   return s;
2968 }
2969
2970 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct)
2971 {
2972   return (sRef_makeCvarAux (level, index, ct));
2973 }
2974
2975 int sRef_lexLevel (sRef s)
2976 {
2977   if (sRef_isValid (s))
2978     {
2979       sRef conj;
2980
2981       conj = sRef_fixConj (s);
2982       s = sRef_getRootBase (conj);
2983       
2984       if (sRef_isValid (s) && s->kind == SK_CVAR)
2985         {
2986           return (s->info->cvar->lexlevel);
2987         }
2988     }
2989
2990   return globScope;
2991 }
2992
2993 sRef
2994 sRef_makeGlobal (usymId l, ctype ct)
2995 {
2996   return (sRef_makeCvar (globScope, l, ct));
2997 }
2998
2999 void
3000 sRef_setParamNo (sRef s, int l)
3001 {
3002   llassert (sRef_isValid (s) && s->kind == SK_PARAM);
3003   s->info->paramno = l;
3004 }
3005
3006 /*@dependent@*/ sRef
3007 sRef_makeParam (int l, ctype ct)
3008 {
3009   sRef s = sRef_new ();
3010
3011   s->kind = SK_PARAM;
3012   s->type = ct;
3013
3014   s->info = (sinfo) dmalloc (sizeof (*s->info));
3015   s->info->paramno = l; 
3016   s->defstate = SS_UNKNOWN; /* (probably defined, unless its an out parameter) */
3017
3018   return s;
3019 }
3020
3021 bool
3022 sRef_isIndexKnown (sRef arr)
3023 {
3024   bool res;
3025
3026   llassert (sRef_isValid (arr));
3027   arr = sRef_fixConj (arr);
3028   
3029   llassert (arr->kind == SK_ARRAYFETCH);  
3030   res = arr->info->arrayfetch->indknown;
3031   return (res);
3032 }
3033
3034 int
3035 sRef_getIndex (sRef arr)
3036 {
3037   int result;
3038
3039   llassert (sRef_isValid (arr));
3040   arr = sRef_fixConj (arr);
3041
3042   llassert (arr->kind == SK_ARRAYFETCH);  
3043
3044   if (!arr->info->arrayfetch->indknown)
3045     {
3046       llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
3047       result = 0; 
3048     }
3049   else
3050     {
3051       result = arr->info->arrayfetch->ind;
3052     }
3053
3054   return result;
3055 }
3056
3057 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
3058 {
3059   return (s->kind == SK_ARRAYFETCH
3060           && s->info->arrayfetch->indknown
3061           && (s->info->arrayfetch->ind == 0));
3062 }
3063
3064 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
3065 {
3066   
3067   if (sRef_isInvalid (t)) return sRef_undefined;
3068
3069   if (sRef_isPointer (t))
3070     {
3071       return (t->info->ref);
3072     }
3073   else if (sRef_isZerothArrayFetch (t))
3074     {
3075       return (t->info->arrayfetch->arr);
3076     }
3077   else
3078     {
3079       sRef s = sRef_new ();
3080       
3081       s->kind = SK_ADR;
3082       s->type = ctype_makePointer (t->type);
3083       s->info = (sinfo) dmalloc (sizeof (*s->info));
3084       s->info->ref = t;
3085       
3086       if (t->defstate == SS_UNDEFINED) 
3087         /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
3088         {
3089           s->defstate = SS_ALLOCATED;
3090         }
3091       else
3092         {
3093           s->defstate = t->defstate;
3094         }
3095
3096       if (t->aliaskind == AK_LOCAL)
3097         {
3098           if (sRef_isLocalVar (t))
3099             {
3100               s->aliaskind = AK_STACK;
3101             }
3102         }
3103
3104       return s;
3105     }
3106 }
3107
3108 cstring sRef_getField (sRef s)
3109 {
3110   cstring res;
3111
3112   llassert (sRef_isValid (s));
3113   s = sRef_fixConj (s);
3114
3115   llassertprint (sRef_isValid (s) && (s->kind == SK_FIELD),
3116                  ("s = %s", sRef_unparseDebug (s)));
3117
3118   res = s->info->field->field;
3119   return (res);
3120 }
3121
3122 sRef sRef_getBase (sRef s)
3123 {
3124   sRef res;
3125
3126   if (sRef_isInvalid (s)) return (sRef_undefined);
3127
3128   s = sRef_fixConj (s);
3129
3130   switch (s->kind)
3131     {
3132     case SK_ADR:
3133     case SK_PTR:
3134     case SK_DERIVED:
3135     case SK_EXTERNAL:
3136       res = s->info->ref;
3137       break;
3138     case SK_FIELD:
3139       res = s->info->field->rec;
3140       break;
3141
3142     case SK_ARRAYFETCH:
3143       res = s->info->arrayfetch->arr;
3144       break;
3145
3146     default:
3147       res = sRef_undefined; /* shouldn't need it */
3148     }
3149
3150   return (res);
3151 }
3152
3153 /*
3154 ** same as getBase, except returns invalid
3155 ** (and doesn't use adr's)                   
3156 */
3157
3158 sRef
3159 sRef_getBaseSafe (sRef s)
3160 {
3161   sRef res;
3162
3163   if (sRef_isInvalid (s)) { return sRef_undefined; }
3164
3165   s = sRef_fixConj (s);
3166
3167   switch (s->kind)
3168     {
3169     case SK_PTR:
3170             res = s->info->ref; 
3171       break;
3172     case SK_FIELD:
3173             res = s->info->field->rec; break;
3174     case SK_ARRAYFETCH:
3175             res = s->info->arrayfetch->arr; 
3176       break;
3177     default:
3178       res = sRef_undefined; break;
3179     }
3180
3181   return res;
3182 }
3183
3184 /*@constant int MAXBASEDEPTH;@*/
3185 # define MAXBASEDEPTH 25
3186
3187 static /*@exposed@*/ sRef 
3188 sRef_getRootBaseAux (sRef s, int depth)
3189 {
3190   if (sRef_isInvalid (s)) return sRef_undefined;
3191
3192   if (depth > MAXBASEDEPTH)
3193     {
3194       llgenmsg (message 
3195                 ("Warning: reference base limit exceeded for %q. "
3196                  "This either means there is a variable with at least "
3197                  "%d indirections from this reference, or "
3198                  "there is a bug in LCLint.",
3199                  sRef_unparse (s),
3200                  MAXBASEDEPTH),
3201                 g_currentloc);
3202
3203       return sRef_undefined;
3204     }
3205
3206   switch (s->kind)
3207     {
3208     case SK_ADR:
3209     case SK_PTR:
3210       return (sRef_getRootBaseAux (s->info->ref, depth + 1));
3211     case SK_FIELD:
3212       return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
3213     case SK_ARRAYFETCH:
3214       return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
3215     case SK_CONJ:
3216       return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
3217     default:
3218       return s;
3219     }
3220 }
3221
3222 sRef sRef_getRootBase (sRef s)
3223 {
3224   return (sRef_getRootBaseAux (s, 0));
3225 }
3226
3227 static bool sRef_isDeep (sRef s)
3228 {
3229   if (sRef_isInvalid (s)) return FALSE;
3230   
3231   switch (s->kind)
3232     {
3233     case SK_ADR:
3234     case SK_PTR:
3235     case SK_FIELD:
3236     case SK_ARRAYFETCH:
3237       return TRUE;
3238     case SK_CONJ:
3239       return (sRef_isDeep (sRef_fixConj (s)));
3240     default:
3241       return FALSE;
3242     }
3243 }
3244
3245 static int sRef_depth (sRef s)
3246 {
3247   if (sRef_isInvalid (s)) return 0;
3248   
3249   switch (s->kind)
3250     {
3251     case SK_ADR:
3252     case SK_PTR:
3253     case SK_DERIVED:
3254     case SK_EXTERNAL:
3255       return 1 + sRef_depth (s->info->ref);
3256     case SK_FIELD:
3257       return 1 + sRef_depth (s->info->field->rec);
3258     case SK_ARRAYFETCH:
3259       return 1 + sRef_depth (s->info->arrayfetch->arr);
3260     case SK_CONJ:
3261       return (sRef_depth (sRef_fixConj (s)));
3262     default:
3263       return 1;
3264     }
3265 }
3266
3267 sRef
3268 sRef_makeObject (ctype o)
3269 {
3270   sRef s = sRef_new ();
3271
3272   s->kind = SK_OBJECT;
3273   s->info = (sinfo) dmalloc (sizeof (*s->info));
3274   s->info->object = o;
3275   return s;
3276 }
3277
3278 sRef sRef_makeExternal (/*@exposed@*/ sRef t)
3279 {
3280   sRef s = sRef_new ();
3281
3282   llassert (sRef_isValid (t));
3283
3284   s->kind = SK_EXTERNAL;
3285   s->info = (sinfo) dmalloc (sizeof (*s->info));
3286   s->type = t->type;
3287   s->info->ref = t;
3288   return s;
3289 }
3290
3291 sRef sRef_makeDerived (/*@exposed@*/ sRef t)
3292 {
3293   if (sRef_isValid (t))
3294     {
3295       sRef s = sRef_new ();
3296       
3297       s->kind = SK_DERIVED;
3298       s->info = (sinfo) dmalloc (sizeof (*s->info));
3299       s->info->ref = t;
3300       
3301       s->type = t->type;
3302       return s;
3303     }
3304   else
3305     {
3306       return sRef_undefined;
3307     }
3308 }
3309
3310 /*
3311 ** definitely NOT symmetric:
3312 **
3313 **   res fills in unknown state information from other
3314 */
3315
3316 void
3317 sRef_mergeStateQuiet (sRef res, sRef other)
3318 {
3319   llassert (sRef_isValid (res));
3320   llassert (sRef_isValid (other));
3321
3322   res->modified = res->modified || other->modified;
3323   res->safe = res->safe && other->safe;
3324
3325   if (res->defstate == SS_UNKNOWN) 
3326     {
3327       res->defstate = other->defstate;
3328       res->definfo = alinfo_update (res->definfo, other->definfo);
3329     }
3330
3331   if (res->aliaskind == AK_UNKNOWN || 
3332       (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
3333     {
3334       res->aliaskind = other->aliaskind;
3335       res->oaliaskind = other->oaliaskind;
3336       res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
3337     }
3338
3339   if (res->expkind == XO_UNKNOWN)
3340     {
3341       res->expkind = other->expkind;
3342       res->oexpkind = other->oexpkind;
3343       res->expinfo = alinfo_update (res->expinfo, other->expinfo);
3344     }
3345   
3346   /* out takes precedence over implicitly defined */
3347   if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN) 
3348     {
3349       res->defstate = other->defstate;
3350       res->definfo = alinfo_update (res->definfo, other->definfo);
3351     }
3352
3353   if (other->nullstate == NS_ERROR || res->nullstate == NS_ERROR) 
3354     {
3355       res->nullstate = NS_ERROR;
3356     }
3357   else
3358     {
3359       if (other->nullstate != NS_UNKNOWN 
3360           && (res->nullstate == NS_UNKNOWN || res->nullstate == NS_NOTNULL 
3361               || res->nullstate == NS_MNOTNULL))
3362         {
3363           res->nullstate = other->nullstate;
3364           res->nullinfo = alinfo_update (res->nullinfo, other->nullinfo);
3365         }
3366     }
3367 }
3368
3369 /*
3370 ** definitely NOT symmetric:
3371 **
3372 **   res fills in known state information from other
3373 */
3374
3375 void
3376 sRef_mergeStateQuietReverse (sRef res, sRef other)
3377 {
3378   bool changed = FALSE;
3379
3380   llassert (sRef_isValid (res));
3381   llassert (sRef_isValid (other));
3382
3383   if (res->kind != other->kind)
3384     {
3385       changed = TRUE;
3386
3387       sinfo_free (res);
3388
3389       res->kind = other->kind;
3390       res->type = other->type;
3391       res->info = sinfo_fullCopy (other);
3392     }
3393   else
3394     {
3395       if (!ctype_equal (res->type, other->type))
3396         {
3397           changed = TRUE;
3398           res->type = other->type;
3399         }
3400       
3401       sinfo_update (res, other);
3402     }
3403
3404   res->modified = res->modified || other->modified;
3405   res->safe = res->safe && other->safe;
3406
3407   if (res->aliaskind != other->aliaskind
3408       && (res->aliaskind == AK_UNKNOWN
3409           || ((res->aliaskind == AK_LOCAL 
3410                || (res->aliaskind == AK_REFCOUNTED
3411                    && other->aliaskind != AK_LOCAL))
3412               && other->aliaskind != AK_UNKNOWN)))
3413     {
3414       changed = TRUE;
3415       res->aliaskind = other->aliaskind;
3416       res->oaliaskind = other->oaliaskind;
3417       res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
3418           }
3419
3420   if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
3421     {
3422       changed = TRUE;
3423       res->expkind = other->expkind;
3424       res->expinfo = alinfo_update (res->expinfo, other->expinfo);
3425     }
3426
3427   if (other->oexpkind != XO_UNKNOWN)
3428     {
3429       res->oexpkind = other->oexpkind;
3430     }
3431
3432   /* out takes precedence over implicitly defined */
3433
3434   if (res->defstate != other->defstate)
3435     {
3436       if (other->defstate != SS_UNKNOWN)
3437         {
3438           res->defstate = other->defstate;
3439         }
3440     }
3441
3442   if (other->nullstate == NS_ERROR || res->nullstate == NS_ERROR)
3443     {
3444       if (res->nullstate != NS_ERROR)
3445         {
3446           res->nullstate = NS_ERROR;
3447           changed = TRUE;
3448         }
3449     }
3450   else
3451     {
3452       if (other->nullstate != NS_UNKNOWN && other->nullstate != res->nullstate)
3453         {
3454           changed = TRUE;
3455           res->nullstate = other->nullstate;
3456           res->nullinfo = alinfo_update (res->nullinfo, other->nullinfo);
3457         }
3458     }
3459
3460   if (changed)
3461     {
3462       sRef_clearDerived (res); 
3463     }
3464 }
3465
3466 void 
3467 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
3468 {
3469   if (sRef_isValid (res) && sRef_isValid (other))
3470     {
3471       sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
3472     }
3473   else
3474     {
3475       if (sRef_isInvalid (res))
3476         {
3477           llbug (message ("sRef_mergeState: invalid res sRef: %q", 
3478                           sRef_unparseDebug (other)));
3479         }
3480       else 
3481         {
3482           llbug (message ("sRef_mergeState: invalid other sRef: %q", 
3483                           sRef_unparseDebug (res)));
3484         }
3485     }
3486 }
3487
3488 void 
3489 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
3490 {
3491   if (sRef_isValid (res) && sRef_isValid (other))
3492     {
3493       sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
3494     }
3495   else
3496     {
3497       if (sRef_isInvalid (res))
3498         {
3499           llbug (message ("sRef_mergeOptState: invalid res sRef: %q", 
3500                           sRef_unparseDebug (other)));
3501         }
3502       else 
3503         {
3504           llbug (message ("sRef_mergeOptState: invalid other sRef: %q", 
3505                           sRef_unparseDebug (res)));
3506         }
3507     }
3508 }
3509
3510 static void
3511 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other, 
3512                     clause cl, bool opt, fileloc loc,
3513                     bool doDerivs)
3514    /*@modifies res@*/ 
3515 {
3516   llassertfatal (sRef_isValid (res));
3517   llassertfatal (sRef_isValid (other));
3518   
3519   res->modified = res->modified || other->modified;
3520
3521   if (res->kind == other->kind 
3522       || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
3523     {
3524       sstate odef = other->defstate;
3525       sstate rdef = res->defstate;
3526       nstate onull = other->nullstate;
3527       
3528       /*
3529       ** yucky stuff to handle 
3530       **
3531       **   if (s) free (s);
3532       */
3533
3534       if (other->defstate == SS_DEAD 
3535           && ((sRef_isOnly (res) && sRef_definitelyNull (res))
3536               || (res->defstate == SS_UNDEFINED
3537                   || res->defstate == SS_UNUSEABLE)))
3538         {
3539           if (res->defstate == SS_UNDEFINED
3540               || res->defstate == SS_UNUSEABLE)
3541             {
3542               res->defstate = SS_UNUSEABLE;
3543             }
3544           else
3545             {
3546               res->defstate = SS_DEAD;
3547             }
3548
3549           res->definfo = alinfo_update (res->definfo, other->definfo);
3550           sRef_clearDerived (other);
3551           sRef_clearDerived (res);
3552         }
3553       else if (res->defstate == SS_DEAD 
3554                && ((sRef_isOnly (other) && sRef_definitelyNull (other))
3555                    || (other->defstate == SS_UNDEFINED
3556                        || other->defstate == SS_UNUSEABLE)))
3557         {
3558           if (other->defstate == SS_UNDEFINED
3559               || other->defstate == SS_UNUSEABLE)
3560             {
3561               res->defstate = SS_UNUSEABLE;
3562             }
3563           else
3564             {
3565               res->defstate = SS_DEAD;
3566             }
3567           
3568           sRef_clearDerived (other);
3569           sRef_clearDerived (res);
3570         }
3571       else if (res->defstate == SS_DEFINED 
3572                && (other->defstate == SS_ALLOCATED 
3573                    && sRef_definitelyNull (other)))
3574         {
3575           other->defstate = SS_DEFINED; /* definitely null! */
3576         }
3577       else if (other->defstate == SS_DEFINED
3578                && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
3579         {
3580           res->defstate = SS_DEFINED;
3581           res->definfo = alinfo_update (res->definfo, other->definfo);
3582         }
3583       else
3584         {
3585           ; /* okay */
3586         }
3587
3588       if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
3589         {
3590           sRef_clearDerived (other);
3591           sRef_clearDerived (res);
3592         }
3593
3594       /*
3595       ** only & dead isn't really an only!
3596       */
3597
3598       if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
3599         {
3600           other->aliaskind = AK_UNKNOWN;
3601         }
3602
3603       if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
3604         {
3605           res->aliaskind = AK_UNKNOWN;
3606         }
3607
3608       /*
3609       ** Dead and dependent -> dead
3610       */
3611       
3612       if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
3613         {
3614           other->aliaskind = AK_UNKNOWN;
3615           other->defstate = SS_DEAD;
3616           sRef_clearDerived (res);
3617           sRef_clearDerived (other);
3618                 }
3619
3620       if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
3621         {
3622           res->aliaskind = AK_UNKNOWN;
3623           res->defstate = SS_DEAD;
3624           sRef_clearDerived (res);
3625           sRef_clearDerived (other);
3626         }
3627
3628       /*
3629       ** must do alias combine first, since it depends on 
3630       ** original values of state and null.
3631       */
3632
3633       sRef_combineAliasKinds (res, other, cl, loc);
3634       sRef_combineDefState (res, other);
3635       sRef_combineNullState (res, other);
3636
3637       if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
3638         {
3639           if (odef == SS_DEFINED)
3640             {
3641               if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
3642                 {
3643                   res->deriv = sRefSet_copy (res->deriv, other->deriv);
3644                 }
3645
3646                               ; 
3647             }
3648           else if (odef == SS_ALLOCATED
3649                    || odef == SS_SPECIAL)
3650             {
3651               
3652               if (doDerivs)
3653                 {
3654                   if (ctype_isUnion (ctype_realType (sRef_getType (res))))
3655                     {
3656                       res->deriv = sRef_mergeUnionDerivs (res->deriv, 
3657                                                           other->deriv, 
3658                                                           opt, cl, loc);
3659                     }
3660                   else
3661                     {
3662                                       res->deriv = sRef_mergeDerivs (res->deriv, other->deriv, 
3663                                                      opt, cl, loc);
3664                     }
3665                 }
3666             }
3667           else
3668             {
3669               if (doDerivs)
3670                 {
3671                                   res->deriv = sRef_mergeDerivs (res->deriv, other->deriv, 
3672                                                  opt, cl, loc);
3673                 }
3674               else
3675                 {
3676                                 }
3677             }
3678         }
3679       else
3680         {
3681           if (rdef == SS_PDEFINED
3682               || (rdef == SS_DEFINED && odef == SS_PDEFINED))
3683             {
3684               if (doDerivs)
3685                 {
3686                                   res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv, 
3687                                                          opt, cl, loc);
3688                 }
3689             }
3690           else
3691             {
3692               if ((rdef == SS_DEFINED  || rdef == SS_UNKNOWN)
3693                   && res->defstate == SS_ALLOCATED)
3694                 {
3695                                   res->deriv = sRefSet_copy (res->deriv, other->deriv);
3696                 }
3697               else
3698                 {
3699                   if (doDerivs)
3700                     {
3701                                       res->deriv = sRef_mergeDerivs (res->deriv, other->deriv, 
3702                                                      opt, cl, loc);
3703                     }
3704                 }
3705             }
3706         }
3707
3708       
3709       sRef_combineExKinds (res, other);
3710     }
3711   else
3712     {
3713       if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
3714         {
3715           sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
3716
3717           sRef_copyState (nother, other);
3718           sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3719         }
3720       else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
3721         {
3722           sRef nother = sRef_buildPointer (sRef_getBase (other));
3723
3724           if (sRef_isValid (nother))
3725             {
3726               sRef_copyState (nother, other);
3727               sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
3728             }
3729         }
3730       else
3731         {
3732           llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res), 
3733                               sRef_unparseFull (other)));
3734           
3735         }
3736     }
3737   
3738   }
3739
3740 static sRefSet
3741 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res, 
3742                        /*@exposed@*/ sRefSet other, bool opt,
3743                        clause cl, fileloc loc)
3744 {
3745   if (sRefSet_isEmpty (res))
3746     {
3747       return sRefSet_copy (res, other);
3748     }
3749   else
3750     {
3751       sRefSet_allElements (other, el)
3752         {
3753           if (sRef_isValid (el))
3754             {
3755               sRef e2 = sRefSet_lookupMember (other, el);
3756               
3757               if (sRef_isValid (e2))
3758                 {
3759                   sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
3760                 }
3761               else
3762                 {
3763                   res = sRefSet_insert (res, el);
3764                 }
3765             }
3766         } end_sRefSet_allElements ;
3767
3768       return res;
3769     }
3770 }
3771
3772 static /*@only@*/ sRefSet
3773 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other, 
3774                   bool opt, clause cl, fileloc loc)
3775 {
3776   sRefSet ret = sRefSet_new ();
3777   
3778     
3779   sRefSet_allElements (res, el)
3780     {
3781       if (sRef_isValid (el))
3782         {
3783           sRef e2 = sRefSet_lookupMember (other, el);
3784
3785           if (sRef_isValid (e2))
3786             {
3787               if (el->defstate == SS_ALLOCATED &&
3788                   e2->defstate == SS_PDEFINED)
3789                 {
3790                   e2->defstate = SS_ALLOCATED;
3791                 }
3792               else if (e2->defstate == SS_ALLOCATED &&
3793                        el->defstate == SS_PDEFINED)
3794                 {
3795                   el->defstate = SS_ALLOCATED;
3796                   sRef_clearDerived (el);
3797                 }
3798               else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
3799                        (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
3800                 {
3801                   
3802                   if (checkDeadState (el, TRUE, loc))
3803                     {
3804                       if (sRef_isThroughArrayFetch (el))
3805                         {
3806                           sRef_maybeKill (el, loc);
3807                           sRef_maybeKill (e2, loc);
3808                         }
3809                     }
3810                 }
3811               else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
3812                        (el->defstate == SS_DEFINED && !sRef_isKept (el)))
3813                 {
3814                   
3815                   if (checkDeadState (e2, FALSE, loc))
3816                     {
3817                       if (sRef_isThroughArrayFetch (el))
3818                         {
3819                           sRef_maybeKill (el, loc);
3820                           sRef_maybeKill (e2, loc);
3821                         }
3822                     }
3823                 }
3824               else if (el->defstate == SS_DEFINED &&
3825                        e2->defstate == SS_PDEFINED)
3826                 {
3827                   el->defstate = SS_PDEFINED;
3828                 }
3829               else if (e2->defstate == SS_DEFINED &&
3830                        el->defstate == SS_PDEFINED)
3831                 {
3832                   e2->defstate = SS_PDEFINED;
3833                 }
3834               else
3835                 {
3836                   ; /* okay */
3837                 }
3838
3839               if (ctype_isUnion (ctype_realType (sRef_getType (el))))
3840                 {
3841                   el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv, 
3842                                                      opt, cl, loc); 
3843                 }
3844               else
3845                 {
3846                   el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc); 
3847                 }
3848               
3849               if (sRef_equivalent (el, e2))
3850                 {
3851                                   ret = sRefSet_insert (ret, el);
3852                 }
3853               else
3854                 {
3855                   sRef sr = sRef_leastCommon (el, e2);
3856
3857                   if (sRef_isValid (sr))
3858                     {
3859                       ret = sRefSet_insert (ret, sr);
3860                     }
3861                   else
3862                     {
3863                       ;
3864                     }
3865                 }
3866               
3867               (void) sRefSet_delete (other, e2);
3868             }
3869           else /* not defined */
3870             {
3871                       (void) checkDeadState (el, TRUE, loc);
3872             }
3873         }
3874     } end_sRefSet_allElements;
3875
3876   sRefSet_allElements (other, el)
3877     {
3878       if (sRef_isValid (el))
3879         {
3880           (void) checkDeadState (el, FALSE, loc);
3881         }
3882     } end_sRefSet_allElements;
3883   
3884   sRefSet_free (res); 
3885   return (ret);
3886 }
3887
3888 /*
3889 ** Returns TRUE is there is an error.
3890 */
3891
3892 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
3893 {
3894   /*
3895   ** usymtab_isGuarded --- the utab should still be in the
3896   ** state of the alternate branch.
3897   **
3898   ** tbranch TRUE means el is released in the last branch, e.g.
3899   **     if (x != NULL) { ; } else { sfree (x); }
3900   ** so, if x is null in the other branch no error is reported.
3901   **
3902   ** tbranch FALSE means this is the other branch:
3903   **     if (x != NULL) { sfree (x); } else { ; }
3904   ** so, if x is null in this branch there is no error.
3905   */
3906
3907   
3908   if ((sRef_isDead (el) || sRef_isKept (el))
3909       && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
3910     {
3911        
3912       if (!tbranch)
3913         {
3914           if (usymtab_isProbableDeepNull (el))
3915             {
3916                       return TRUE;
3917             }
3918         }
3919       else
3920         {
3921           if (usymtab_isAltProbablyDeepNull (el))
3922             {
3923                       return TRUE;
3924             }
3925         }
3926
3927       if (optgenerror
3928           (FLG_BRANCHSTATE,
3929            message ("Storage %q is %q in one path, but live in another.",
3930                     sRef_unparse (el),
3931                     cstring_makeLiteral (sRef_isKept (el) 
3932                                          ? "kept" : "released")),
3933            loc))
3934         {
3935                   
3936           if (sRef_isKept (el))
3937             {
3938               sRef_showAliasInfo (el);      
3939             }
3940           else
3941             {
3942               sRef_showStateInfo (el);
3943             }
3944
3945           /* prevent further errors */
3946           el->defstate = SS_UNKNOWN; 
3947           sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
3948           
3949           return FALSE;
3950         }
3951     }
3952
3953   return TRUE;
3954 }
3955
3956 static void 
3957 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
3958 {
3959   
3960   if (checkDeadState (el, tbranch, loc))
3961     {
3962       sRefSet_allElements (el->deriv, t)
3963         {
3964           if (sRef_isValid (t))
3965             {
3966                       checkDerivDeadState (t, tbranch, loc);
3967             }
3968         } end_sRefSet_allElements;
3969     }
3970 }
3971
3972 static sRefSet
3973   sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt, 
3974                             clause cl, fileloc loc)
3975 {
3976   sRefSet ret = sRefSet_new ();
3977
3978   sRefSet_allElements (res, el)
3979     {
3980       if (sRef_isValid (el))
3981         {
3982           sRef e2 = sRefSet_lookupMember (other, el);
3983           
3984           if (sRef_isValid (e2))
3985             {
3986               if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
3987                 {
3988                   ;
3989                 }
3990               else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
3991                 {
3992                   el->deriv = sRefSet_copy (el->deriv, e2->deriv); 
3993                 }
3994               else
3995                 {
3996                   el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv, 
3997                                                         opt, cl, loc);
3998                 }
3999
4000               sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
4001               
4002               ret = sRefSet_insert (ret, el);
4003               (void) sRefSet_delete (other, e2);
4004             }
4005           else
4006             {
4007               if (!opt)
4008                 {
4009                                   checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
4010                 }
4011
4012               ret = sRefSet_insert (ret, el);
4013             }
4014         }
4015     } end_sRefSet_allElements;
4016   
4017   sRefSet_allElements (other, el)
4018     {
4019       if (sRef_isValid (el))
4020         {
4021           if (!sRefSet_member (ret, el))
4022             {
4023                               /* was cl == FALSECLAUSE */
4024               checkDerivDeadState (el, FALSE, loc);
4025               ret = sRefSet_insert (ret, el);
4026             }
4027           else
4028             {
4029               /*
4030               ** it's okay --- member is a different equality test 
4031               */
4032             }
4033         }
4034     } end_sRefSet_allElements;
4035
4036   sRefSet_free (res);
4037   return (ret);
4038 }
4039
4040 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
4041 {
4042   llassert (sRef_isValid (a));
4043   llassert (sRef_isValid (b));
4044       
4045   if (!sRef_equivalent (a, b))
4046     {
4047       sRef s = sRef_new ();
4048       
4049       s->kind = SK_CONJ;
4050       s->info = (sinfo) dmalloc (sizeof (*s->info));
4051       s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
4052       s->info->conj->a = a;
4053       s->info->conj->b = b;
4054       
4055       if (ctype_equal (a->type, b->type)) s->type = a->type;
4056       else s->type = ctype_makeConj (a->type, b->type);
4057       
4058       if (a->defstate == b->defstate)
4059         {
4060           s->defstate = a->defstate;
4061         }
4062       else
4063         {
4064           s->defstate = SS_UNKNOWN; 
4065         }
4066       
4067       s->nullstate = NS_UNKNOWN;
4068       
4069       s->safe = a->safe && b->safe;
4070       s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
4071
4072       return s;
4073     }
4074   else
4075     {
4076       /*@-exposetrans@*/ return a; /*@=exposetrans@*/
4077     }
4078 }
4079
4080 sRef
4081 sRef_makeUnknown ()
4082 {
4083   sRef s = sRef_new ();
4084
4085   s->kind = SK_UNKNOWN;
4086   return s;
4087 }
4088
4089 static sRef
4090 sRef_makeSpecial (speckind sk) /*@*/
4091 {
4092   sRef s = sRef_new ();
4093
4094   s->kind = SK_SPECIAL;
4095   s->info = (sinfo) dmalloc (sizeof (*s->info));
4096   s->info->spec = sk;
4097   return s;
4098 }
4099
4100 static sRef srnothing = sRef_undefined;
4101 static sRef srinternal = sRef_undefined;
4102 static sRef srsystem = sRef_undefined;
4103 static sRef srspec = sRef_undefined;
4104
4105 sRef
4106 sRef_makeNothing (void)
4107 {
4108   if (sRef_isInvalid (srnothing))
4109     {
4110       srnothing = sRef_makeSpecial (SR_NOTHING);
4111     }
4112
4113   /*@-retalias@*/
4114   return srnothing;
4115   /*@=retalias@*/
4116 }
4117
4118 sRef
4119 sRef_makeInternalState (void)
4120 {
4121   if (sRef_isInvalid (srinternal))
4122     {
4123       srinternal = sRef_makeSpecial (SR_INTERNAL);
4124     }
4125
4126   /*@-retalias@*/
4127   return srinternal;
4128   /*@=retalias@*/
4129 }
4130
4131 sRef
4132 sRef_makeSpecState (void)
4133 {
4134   if (sRef_isInvalid (srspec))
4135     {
4136       srspec = sRef_makeSpecial (SR_SPECSTATE);
4137     }
4138
4139   /*@-retalias@*/
4140   return srspec;
4141   /*@=retalias@*/
4142 }
4143
4144 sRef
4145 sRef_makeSystemState (void)
4146 {
4147   if (sRef_isInvalid (srsystem))
4148     {
4149       srsystem = sRef_makeSpecial (SR_SYSTEM);
4150     }
4151
4152   /*@-retalias@*/
4153   return (srsystem);
4154   /*@=retalias@*/
4155 }
4156
4157 static sRef
4158 sRef_makeResultType (ctype ct)
4159 {
4160   sRef res = sRef_makeResult ();
4161
4162   res->type = ct;
4163   return res;
4164 }
4165
4166 sRef
4167 sRef_makeResult ()
4168 {
4169   sRef s = sRef_new ();
4170   
4171   s->kind = SK_RESULT;
4172   s->type = ctype_unknown;
4173   s->defstate = SS_UNKNOWN; 
4174   s->aliaskind = AK_UNKNOWN;
4175   s->nullstate = NS_UNKNOWN;
4176   
4177   return s;
4178 }
4179
4180
4181 bool
4182 sRef_isNothing (sRef s)
4183 {
4184   return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
4185 }
4186
4187 bool
4188 sRef_isInternalState (sRef s)
4189 {
4190   return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
4191 }
4192
4193 bool
4194 sRef_isSpecInternalState (sRef s)
4195 {
4196   return (sRef_isKindSpecial (s) 
4197           && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
4198 }
4199
4200 bool
4201 sRef_isSpecState (sRef s)
4202 {
4203   return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
4204 }
4205
4206 bool
4207 sRef_isResult (sRef s)
4208 {
4209   return (sRef_isValid (s) && s->kind == SK_RESULT);
4210 }
4211
4212 bool
4213 sRef_isSystemState (sRef s)
4214 {
4215   return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
4216 }
4217
4218 usymId
4219 sRef_getScopeIndex (sRef s)
4220 {
4221   llassert (sRef_isValid (s));
4222   llassert (sRef_isCvar (s));
4223
4224   return (s->info->cvar->index);
4225 }
4226
4227 void
4228 sRef_makeSafe (sRef s)
4229 {
4230   if (sRef_isValid (s)) 
4231     {
4232       s->safe = TRUE;
4233     }
4234 }
4235
4236 void
4237 sRef_makeUnsafe (sRef s)
4238 {
4239   if (sRef_isValid (s)) 
4240     {
4241       s->safe = FALSE;
4242     }
4243 }
4244
4245 /*
4246 ** memory state operations
4247 */
4248
4249 /*@only@*/ cstring sRef_unparseFull (sRef s)
4250 {
4251   if (sRef_isInvalid (s)) return (cstring_undefined);
4252
4253   return (message ("[%d] %q - %q [%s] { %q }", 
4254                    (int) s,
4255                    sRef_unparseDebug (s), 
4256                    sRef_unparseState (s),
4257                    exkind_unparse (s->oexpkind),
4258                    sRefSet_unparseDebug (s->deriv)));
4259 }
4260
4261 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
4262 {
4263   cstring st = cstring_undefined;
4264
4265   st = message ("%q:", sRef_unparseFull (s));
4266
4267   if (sRef_isValid (s))
4268     {
4269       sRefSet_allElements (s->deriv, el)
4270         {
4271           st = message("%q\n%q", st, sRef_unparseDeep (el));
4272         } end_sRefSet_allElements ;
4273     }
4274
4275   return st;
4276 }
4277
4278 /*@only@*/ cstring sRef_unparseState (sRef s)
4279 {
4280   if (sRef_isConj (s))
4281     {
4282       return (message ("%q | %q", 
4283                        sRef_unparseState (s->info->conj->a),
4284                        sRef_unparseState (s->info->conj->b)));
4285     }
4286
4287   if (sRef_isInvalid (s))
4288     {
4289       return (cstring_makeLiteral ("<invalid>"));
4290     }
4291
4292   return (message ("%s.%s.%s.%s", 
4293                    alkind_unparse (s->aliaskind), 
4294                    nstate_unparse (s->nullstate),
4295                    exkind_unparse (s->expkind),
4296                    sstate_unparse (s->defstate)));
4297 }
4298
4299 bool sRef_isNotUndefined (sRef s)
4300 {
4301   return (sRef_isInvalid (s)
4302           || (s->defstate != SS_UNDEFINED
4303               && s->defstate != SS_UNUSEABLE
4304               && s->defstate != SS_DEAD));
4305 }
4306
4307 ynm sRef_isWriteable (sRef s)
4308 {
4309   if (sRef_isInvalid (s)) return MAYBE;
4310
4311   if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4312     {
4313       if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
4314         {
4315           if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4316             {
4317               return YES;
4318             }
4319           return MAYBE;
4320         }
4321       else
4322         {
4323           if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
4324             {
4325               return MAYBE;
4326             }
4327           return NO;
4328         }
4329     }
4330
4331   return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
4332 }
4333
4334 bool sRef_hasNoStorage (sRef s)
4335 {
4336   return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
4337 }
4338
4339 bool sRef_isStrictReadable (sRef s)
4340 {
4341   return (ynm_toBoolStrict (sRef_isReadable (s)));
4342 }
4343
4344 ynm sRef_isReadable (sRef s)
4345 {
4346   sstate ss;
4347
4348   if (sRef_isInvalid (s)) return YES;
4349
4350   ss = s->defstate;
4351   
4352   if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
4353     {
4354       if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjA (s))))
4355         {
4356           if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4357             {
4358               return YES;
4359             }
4360           return MAYBE;
4361         }
4362       else
4363         {
4364           if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
4365             {
4366               return MAYBE;
4367             }
4368           return NO;
4369         }
4370     }
4371   else if (ss == SS_HOFFA)
4372     {
4373       if (context_getFlag (FLG_STRICTUSERELEASED))
4374         {
4375           return MAYBE;
4376         }
4377       else
4378         {
4379           return YES;
4380         }
4381     }
4382   else
4383     {
4384       return (ynm_fromBool (ss == SS_DEFINED 
4385                             || ss == SS_FIXED 
4386                             || ss == SS_RELDEF 
4387                             || ss == SS_PDEFINED 
4388                             || ss == SS_PARTIAL
4389                             || ss == SS_SPECIAL
4390                             || ss == SS_ALLOCATED
4391                             || ss == SS_UNKNOWN));
4392     }
4393 }
4394
4395 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
4396 {
4397   ctype ct;
4398
4399   
4400   if (depth > MAXDEPTH)
4401     {
4402       llgenmsg (message 
4403                 ("Warning: check definition limit exceeded, checking %q. "
4404                  "This either means there is a variable with at least "
4405                  "%d indirections apparent in the program text, or "
4406                  "there is a bug in LCLint.",
4407                  sRef_unparse (fref),
4408                  MAXDEPTH),
4409                 g_currentloc);
4410
4411       return sRef_undefined;
4412     }
4413
4414   if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
4415     {
4416       return sRef_undefined;
4417     }
4418
4419   if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
4420     {
4421       return fref;
4422     }
4423
4424   ct = ctype_realType (sRef_getType (fref));
4425   
4426   if (ctype_isUnknown (ct))
4427     {
4428       return sRef_undefined;
4429     }
4430   else if (ctype_isPointer (ct) || ctype_isArray (ct))
4431     {
4432       if (sRef_isStateUnknown (fref))
4433         {
4434           return sRef_undefined;
4435         }
4436       else
4437         {
4438           sRef fptr = sRef_constructDeref (fref);
4439
4440           return (whatUndefined (fptr, depth + 1));
4441         }
4442     }
4443   else if (ctype_isStruct (ct))
4444     {
4445       bool hasOneDefined = FALSE;
4446       
4447       if (sRef_isStateUnknown (fref))
4448         {
4449           return fref;
4450         }
4451           
4452       if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
4453         {
4454           sRefSet_realElements (sRef_derivedFields (fref), sr)
4455             {
4456               hasOneDefined = TRUE;
4457               
4458               if (sRef_isField (sr))
4459                 {
4460                   cstring fieldname = sRef_getField (sr);
4461                   sRef fldref = sRef_makeField (fref, fieldname);
4462                   bool shouldCheck = !sRef_isRecursiveField (fldref);
4463                   
4464                   if (shouldCheck)
4465                     {
4466                       sRef wdef = whatUndefined (fldref, depth + 1);
4467
4468                       if (sRef_isValid (wdef))
4469                         {
4470                           return wdef;
4471                         }
4472                     }
4473                 }
4474             } end_sRefSet_realElements;
4475         }
4476       else if (sRef_isAllocated (fref))
4477         {
4478           /*
4479           ** for structures, each field must be completely defined
4480           */
4481           
4482           uentryList fields = ctype_getFields (ct);
4483               
4484           uentryList_elements (fields, ue)
4485             {
4486               cstring name = uentry_getRealName (ue);
4487               sRef ffield = sRef_makeField (fref, name);
4488               bool shouldCheck = !sRef_isRecursiveField (ffield);
4489
4490               if (sRef_isRelDef (uentry_getSref (ue)))
4491                 {
4492                   ; /* no error */
4493                 }
4494               else
4495                 {
4496                   if (shouldCheck)
4497                     {
4498                       sRef wdef = whatUndefined (ffield, depth + 1);
4499
4500                       if (sRef_isInvalid (wdef))
4501                         {
4502                           return wdef;
4503                         }
4504                     }
4505                 }
4506             } end_uentryList_elements;
4507         }
4508       else
4509         {
4510           ;
4511         }
4512     }
4513   else if (ctype_isUnion (ct))
4514     {
4515       ; 
4516     }
4517   else
4518     {
4519       ;
4520     }
4521
4522   return sRef_undefined;
4523 }
4524
4525 static bool checkDefined (sRef sr)
4526 {
4527   return (sRef_isInvalid (whatUndefined (sr, 0)));
4528 }
4529
4530 bool sRef_isReallyDefined (sRef s)
4531 {
4532   if (sRef_isValid (s))
4533     {
4534       if (sRef_isAnyDefined (s))
4535         {
4536           return TRUE;
4537         }
4538       else
4539         {
4540           if (sRef_isAllocated (s) || sRef_isPdefined (s))
4541             {
4542               return checkDefined (s);
4543             }
4544           else
4545             {
4546               return FALSE;
4547             }
4548         }
4549     }
4550   else
4551     {
4552       return TRUE;
4553     }
4554 }
4555
4556 void sRef_showNotReallyDefined (sRef s)
4557 {
4558   if (sRef_isValid (s))
4559     {
4560       if (sRef_isAnyDefined (s))
4561         {
4562           BADBRANCH;
4563         }
4564       else
4565         {
4566           if (sRef_isAllocated (s) || sRef_isPdefined (s))
4567             {
4568               sRef ref = whatUndefined (s, 0);
4569
4570               llassert (sRef_isValid (ref));
4571
4572               if (ref != s)
4573                 {
4574                   llgenindentmsgnoloc
4575                     (message ("This sub-reference is %s: %q",
4576                               sstate_unparse (sRef_getDefState (ref)),
4577                               sRef_unparse (ref)));
4578                 }
4579             }
4580           else
4581             {
4582               ;
4583             }
4584         }
4585     }
4586   else
4587     {
4588       BADBRANCH;
4589     }
4590 }
4591
4592 sstate sRef_getDefState (sRef s)
4593 {
4594   if (sRef_isInvalid (s)) return (SS_UNKNOWN);
4595   return (s->defstate);
4596 }
4597
4598 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
4599 {
4600   sRef_setStateAux (s, defstate, loc);
4601 }
4602
4603 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
4604 {
4605   sRef_setAliasKind (s, AK_ERROR, loc);
4606 }
4607
4608 void sRef_clearAliasState (sRef s, fileloc loc)
4609 {
4610   sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
4611 }
4612
4613 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
4614 {
4615   sRef_aliasSetCompleteParam (sRef_setAliasKind, s, kind, loc);
4616 }
4617
4618 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
4619 {
4620   if (sRef_isValid (s))
4621     {
4622       sRef_clearDerived (s);
4623
4624       if ((kind != s->aliaskind && kind != s->oaliaskind)
4625           && fileloc_isDefined (loc))
4626         {
4627           s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
4628         }
4629       
4630       s->aliaskind = kind;
4631     }
4632 }
4633
4634 void sRef_setOrigAliasKind (sRef s, alkind kind)
4635 {
4636   if (sRef_isValid (s))
4637     {
4638       s->oaliaskind = kind;
4639     }
4640 }
4641
4642 exkind sRef_getExKind (sRef s)
4643 {
4644   if (sRef_isValid (s))
4645     {
4646       return (s->expkind);
4647     }
4648   else
4649     {
4650       return XO_UNKNOWN;
4651     }
4652 }
4653
4654 exkind sRef_getOrigExKind (sRef s)
4655 {
4656   if (sRef_isValid (s))
4657     {
4658       return (s->oexpkind);
4659     }
4660   else
4661     {
4662       return XO_UNKNOWN;
4663     }
4664 }
4665
4666 static void sRef_clearExKindAux (sRef s, fileloc loc)
4667 {
4668   sRef_setExKind (s, XO_UNKNOWN, loc);
4669 }
4670
4671 void sRef_setObserver (sRef s, fileloc loc) 
4672 {
4673   sRef_setExKind (s, XO_OBSERVER, loc);
4674 }
4675
4676 void sRef_setExposed (sRef s, fileloc loc) 
4677 {
4678   sRef_setExKind (s, XO_EXPOSED, loc);
4679 }
4680
4681 void sRef_clearExKindComplete (sRef s, fileloc loc)
4682 {
4683   (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
4684 }
4685
4686 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
4687 {
4688   if (sRef_isValid (s))
4689     {
4690       if (s->expkind != exp)
4691         {
4692           s->expinfo = alinfo_updateLoc (s->expinfo, loc);
4693         }
4694       
4695       s->expkind = exp;
4696     }
4697 }
4698
4699 /*
4700 ** s1->derived = s2->derived
4701 */
4702
4703 static void sRef_copyRealDerived (sRef s1, sRef s2)
4704 {
4705   if (sRef_isValid (s1) && sRef_isValid (s2))
4706     {
4707       sRef sb = sRef_getRootBase (s1);
4708
4709       sRefSet_clear (s1->deriv);
4710
4711       sRefSet_allElements (s2->deriv, el)
4712         {
4713           if (sRef_isValid (el))
4714             {
4715               sRef rb = sRef_getRootBase (el);
4716               
4717               if (!sRef_same (rb, sb))
4718                 {
4719                   sRef fb = sRef_fixDirectBase (el, s1);
4720                   
4721                   if (sRef_isValid (fb))
4722                     {
4723                       sRef_copyRealDerived (fb, el);
4724                       sRef_addDeriv (s1, fb);
4725                     }
4726                 }
4727               else
4728                 {
4729                   sRef_addDeriv (s1, el);
4730                 }
4731             }
4732         } end_sRefSet_allElements ;
4733     }
4734   
4735   }
4736
4737 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
4738 {
4739   sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
4740 }
4741
4742 void sRef_setUndefined (sRef s, fileloc loc)
4743 {
4744   if (sRef_isValid (s))
4745     {
4746       s->defstate = SS_UNDEFINED;
4747
4748       if (fileloc_isDefined (loc))
4749         {
4750           s->definfo = alinfo_updateLoc (s->definfo, loc);
4751         }
4752
4753       sRef_clearDerived (s);
4754     }
4755 }
4756
4757 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
4758 {
4759   if (sRef_isInvalid (s)) return;
4760
4761   if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
4762     {
4763       s->definfo = alinfo_updateLoc (s->definfo, loc);
4764     }
4765   
4766   s->defstate = SS_DEFINED;
4767   
4768   /* e.g., if x is allocated, *x = 3 defines x */
4769   
4770   if (s->kind == SK_PTR)
4771     {
4772       sRef p = s->info->ref;
4773       
4774       if (p->defstate == SS_ALLOCATED)
4775         {
4776           sRef_setDefinedAux (p, loc, clear);
4777         }
4778     }
4779   else if (s->kind == SK_ARRAYFETCH) 
4780     {
4781       if (!s->info->arrayfetch->indknown
4782           || (s->info->arrayfetch->ind == 0))
4783         {
4784           sRef p = s->info->arrayfetch->arr;
4785           sRef ptr = sRef_constructPointer (p);
4786           
4787           if (sRef_isValid (ptr))
4788             {
4789               if (ptr->defstate == SS_ALLOCATED 
4790                   || ptr->defstate == SS_UNDEFINED)
4791                 {
4792                   sRef_setDefinedAux (ptr, loc, clear);
4793                 }
4794             }
4795           
4796           if (p->defstate == SS_RELDEF) 
4797             {
4798               ;
4799             }
4800           else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED)
4801             {
4802               p->defstate = SS_DEFINED;
4803             }
4804           else
4805             {
4806             }
4807         }
4808     }
4809   else if (s->kind == SK_FIELD)
4810     {
4811       sRef parent = s->info->field->rec;
4812       
4813       if (sRef_isValid (parent))
4814         {
4815           if (ctype_isUnion (ctype_realType (parent->type)))
4816             {
4817               /*
4818               ** Should not clear derived from here.
4819               */
4820               
4821               sRef_setDefinedNoClear (parent, loc);
4822             }
4823           else
4824             {
4825               ; /* Nothing to do for structures. */
4826             }
4827         }
4828
4829           }
4830   else
4831     {
4832       ;
4833     }
4834
4835   if (clear)
4836     {
4837       sRef_clearDerived (s);
4838     }  
4839 }
4840
4841 static void sRef_setPartialDefined (sRef s, fileloc loc)
4842 {
4843   if (!sRef_isPartial (s))
4844     {
4845       sRef_setDefined (s, loc);
4846     }
4847 }
4848
4849 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
4850 {
4851   sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
4852 }
4853
4854 void sRef_setDefinedComplete (sRef s, fileloc loc)
4855 {
4856   sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
4857 }
4858
4859 void sRef_setDefined (sRef s, fileloc loc)
4860 {
4861   sRef_setDefinedAux (s, loc, TRUE);
4862 }
4863
4864 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
4865 {
4866   DPRINTF (("Defining: %s", sRef_unparseFull (s)));
4867   sRef_setDefinedAux (s, loc, FALSE);
4868   DPRINTF (("==> %s", sRef_unparseFull (s)));
4869 }
4870
4871 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
4872 {
4873   DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
4874   sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
4875   DPRINTF (("==> %s", sRef_unparseFull (s)));
4876 }
4877
4878 static bool sRef_isDeepUnionField (sRef s)
4879 {
4880   return (sRef_deepPred (sRef_isUnionField, s));
4881 }
4882
4883 bool sRef_isUnionField (sRef s)
4884 {
4885   if (sRef_isValid (s) && s->kind == SK_FIELD)
4886     {
4887       /*
4888        ** defining one field of a union defines the union
4889        */
4890       
4891       sRef base = s->info->field->rec;
4892
4893       if (sRef_isValid (base))
4894         {
4895           return (ctype_isUnion (ctype_realType (base->type)));
4896         }
4897     }
4898
4899   return FALSE;
4900 }
4901
4902 void sRef_setPdefined (sRef s, fileloc loc)
4903 {
4904   if (sRef_isValid (s) && !sRef_isPartial (s))
4905     {
4906       sRef base = sRef_getBaseSafe (s);
4907
4908       if (s->defstate == SS_ALLOCATED)
4909         {
4910           return;
4911         }
4912       
4913       if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
4914         {
4915           s->definfo = alinfo_updateLoc (s->definfo, loc);
4916         }
4917
4918       s->defstate = SS_PDEFINED;
4919       
4920       /* e.g., if x is allocated, *x = 3 defines x */
4921       
4922       while (sRef_isValid (base) && sRef_isKnown (base))
4923         {
4924           if (base->defstate == SS_DEFINED)
4925             { 
4926               sRef nb;
4927
4928                       base->defstate = SS_PDEFINED; 
4929               nb = sRef_getBaseSafe (base); 
4930               base = nb;
4931             }
4932           else 
4933             { 
4934               break; 
4935             }
4936         }      
4937     }
4938 }
4939
4940 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
4941 {
4942   if (sRef_isValid (s))
4943     {
4944       /* if (s->defstate == SS_RELDEF) return; */
4945
4946       if (s->defstate != ss && fileloc_isDefined (loc))
4947         {
4948           s->definfo = alinfo_updateLoc (s->definfo, loc);
4949         }
4950
4951       s->defstate = ss;
4952       sRef_clearDerived (s); 
4953
4954       if (ss == SS_ALLOCATED)
4955         {
4956           sRef base = sRef_getBaseSafe (s);
4957           
4958           while (sRef_isValid (base) && sRef_isKnown (base))
4959             {
4960               if (base->defstate == SS_DEFINED) 
4961                 { 
4962                   sRef nb;
4963                   
4964                   base->defstate = SS_PDEFINED; 
4965                   
4966                   nb = sRef_getBaseSafe (base); 
4967                   base = nb;
4968                 }
4969               else 
4970                 { 
4971                   break; 
4972                 }
4973             }
4974         }
4975
4976           }
4977 }
4978
4979 void sRef_setAllocatedComplete (sRef s, fileloc loc)
4980 {
4981   sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
4982 }
4983
4984 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
4985 {
4986   if (sRef_isValid (s))
4987     {
4988       if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
4989         {
4990           s->defstate = SS_ALLOCATED;
4991           
4992           if (fileloc_isDefined (loc))
4993             {
4994               s->definfo = alinfo_updateLoc (s->definfo, loc);
4995             }
4996         }
4997     }
4998 }
4999
5000 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
5001 {
5002   sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
5003 }
5004
5005 void sRef_setAllocated (sRef s, fileloc loc)
5006 {
5007   sRef_setStateAux (s, SS_ALLOCATED, loc);
5008   }
5009
5010 void sRef_setPartial (sRef s, fileloc loc)
5011 {
5012   sRef_setStateAux (s, SS_PARTIAL, loc);
5013   }
5014
5015 void sRef_setShared (sRef s, fileloc loc)
5016 {
5017   if (sRef_isValid (s))
5018     {
5019       if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
5020         {
5021           s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5022         }
5023
5024       s->aliaskind = AK_SHARED;
5025       /* don't! sRef_clearDerived (s); */
5026     }
5027 }
5028
5029 void sRef_setLastReference (sRef s, sRef ref, fileloc loc)
5030 {
5031   if (sRef_isValid (s))
5032     {
5033       s->aliaskind = sRef_getAliasKind (ref);
5034       s->aliasinfo = alinfo_updateRefLoc (s->aliasinfo, ref, loc);
5035     }
5036 }
5037
5038 static
5039 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
5040 {
5041  s->nullstate = ns;
5042
5043  if (fileloc_isDefined (loc))
5044    {
5045      s->nullinfo = alinfo_updateLoc (s->nullinfo, loc);
5046    }
5047 }
5048
5049 void sRef_setNotNull (sRef s, fileloc loc)
5050 {
5051   if (sRef_isValid (s))
5052     {
5053       sRef_setNullStateAux (s, NS_NOTNULL, loc);
5054     }
5055 }
5056
5057 void sRef_setNullState (sRef s, nstate n, fileloc loc)
5058 {
5059   if (sRef_isValid (s))
5060     {
5061       sRef_setNullStateAux (s, n, loc);
5062     }
5063 }
5064
5065 void sRef_setNullTerminatedStateInnerComplete (sRef s, struct _bbufinfo b, /*@unused@*/ fileloc loc) {
5066    
5067   switch (b.bufstate) {
5068      case BB_NULLTERMINATED:
5069           sRef_setNullTerminatedState (s);
5070           sRef_setLen (s, b.len);
5071           break;
5072      case BB_POSSIBLYNULLTERMINATED:
5073           sRef_setPossiblyNullTerminatedState(s);
5074           break;
5075      case BB_NOTNULLTERMINATED:
5076           sRef_setNotNullTerminatedState (s);
5077           break;
5078   }
5079   sRef_setSize (s, b.size);
5080
5081   /* PL: TO BE DONE : Aliases are not modified right now, have to be similar to
5082    * setNullStateInnerComplete.
5083    */
5084 }
5085
5086 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
5087 {
5088   sRef_setNullState (s, n, loc);
5089
5090   switch (n)
5091     {
5092     case NS_POSNULL:
5093       sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
5094       break;
5095     case NS_DEFNULL:
5096       sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5097       break;
5098     case NS_UNKNOWN:
5099       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5100       break;
5101     case NS_NOTNULL:
5102       sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5103       break;
5104     case NS_MNOTNULL:
5105       sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
5106       break;
5107     case NS_RELNULL:
5108       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5109       break;
5110     case NS_CONSTNULL:
5111       sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
5112       break;
5113     case NS_ABSNULL:
5114       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
5115       break;
5116     case NS_ERROR:
5117       sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
5118       break;
5119     }
5120 }
5121
5122 void sRef_setPosNull (sRef s, fileloc loc)
5123 {
5124   if (sRef_isValid (s))
5125     {
5126       sRef_setNullStateAux (s, NS_POSNULL, loc);
5127     }
5128 }
5129   
5130 void sRef_setDefNull (sRef s, fileloc loc)
5131 {
5132   if (sRef_isValid (s))
5133     {
5134       sRef_setNullStateAux (s, NS_DEFNULL, loc);
5135     }
5136 }
5137
5138 void sRef_setNullUnknown (sRef s, fileloc loc)
5139 {
5140   if (sRef_isValid (s))
5141     {
5142       sRef_setNullStateAux (s, NS_UNKNOWN, loc);
5143     }
5144 }
5145
5146 void sRef_setNullError (sRef s)
5147 {
5148   if (sRef_isValid (s))
5149     {
5150       sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
5151     }
5152 }
5153
5154 void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
5155 {
5156   sRef_setNullError (s);
5157 }
5158
5159 void sRef_setOnly (sRef s, fileloc loc)
5160 {
5161   if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
5162     {
5163       s->aliaskind = AK_ONLY;
5164       s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5165           }
5166 }
5167
5168 void sRef_setDependent (sRef s, fileloc loc)
5169 {
5170   if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
5171     {
5172       s->aliaskind = AK_DEPENDENT;
5173       s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5174           }
5175 }
5176
5177 void sRef_setOwned (sRef s, fileloc loc)
5178 {
5179   if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
5180     {
5181       s->aliaskind = AK_OWNED;
5182       s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5183           }
5184 }
5185
5186 void sRef_setKept (sRef s, fileloc loc)
5187 {
5188   if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
5189     {
5190       sRef base = sRef_getBaseSafe (s);  
5191       
5192       while (sRef_isValid (base) && sRef_isKnown (base))
5193         {
5194           if (base->defstate == SS_DEFINED) 
5195             {
5196               base->defstate = SS_PDEFINED; 
5197                       base = sRef_getBaseSafe (base); 
5198             }
5199           else 
5200             {
5201               break; 
5202             }
5203
5204         }
5205
5206       s->aliaskind = AK_KEPT;
5207       s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5208           }
5209 }
5210
5211 static void sRef_setKeptAux (sRef s, fileloc loc)
5212 {
5213   if (!sRef_isShared (s))
5214     {
5215       sRef_setKept (s, loc);
5216     }
5217 }
5218
5219 static void sRef_setDependentAux (sRef s, fileloc loc)
5220 {
5221   if (!sRef_isShared (s))
5222     {
5223       sRef_setDependent (s, loc);
5224     }
5225 }
5226
5227 void sRef_setKeptComplete (sRef s, fileloc loc)
5228 {
5229   sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
5230 }
5231
5232 void sRef_setDependentComplete (sRef s, fileloc loc)
5233 {
5234   sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
5235 }
5236
5237 void sRef_setFresh (sRef s, fileloc loc)
5238 {
5239   if (sRef_isValid (s))
5240     {
5241       s->aliaskind = AK_FRESH;
5242       s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
5243     }
5244 }
5245
5246 void sRef_kill (sRef s, fileloc loc)
5247 {
5248   DPRINTF (("Kill: %s", sRef_unparseFull (s)));
5249
5250   if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
5251     {
5252       sRef base = sRef_getBaseSafe (s);  
5253       
5254       while (sRef_isValid (base) && sRef_isKnown (base))
5255         {
5256           if (base->defstate == SS_DEFINED) 
5257             {
5258               base->defstate = SS_PDEFINED; 
5259               base = sRef_getBaseSafe (base); 
5260             }
5261           else 
5262             {
5263               break; 
5264             }
5265
5266         }
5267       
5268       s->aliaskind = s->oaliaskind;
5269       s->defstate = SS_DEAD;
5270       s->definfo = alinfo_updateLoc (s->definfo, loc);
5271
5272       sRef_clearDerived (s);
5273     }
5274 }
5275
5276 void sRef_maybeKill (sRef s, fileloc loc)
5277 {
5278         
5279   if (sRef_isValid (s))
5280     {
5281       sRef base = sRef_getBaseSafe (s);  
5282
5283             
5284       while (sRef_isValid (base) && sRef_isKnown (base))
5285         {
5286           if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
5287             {
5288               base->defstate = SS_PDEFINED; 
5289                       base = sRef_getBaseSafe (base); 
5290             }
5291           else 
5292             {
5293                       break; 
5294             }
5295           
5296         }
5297       
5298       s->aliaskind = s->oaliaskind;
5299       s->defstate = SS_HOFFA; 
5300       s->definfo = alinfo_updateLoc (s->definfo, loc);
5301       sRef_clearDerived (s); 
5302     }
5303
5304   }
5305
5306 /*
5307 ** just for type checking...
5308 */
5309
5310 static void sRef_killAux (sRef s, fileloc loc)
5311 {
5312   if (sRef_isValid (s) && !sRef_isShared (s))
5313     {
5314       if (sRef_isUnknownArrayFetch (s))
5315         {
5316           sRef_maybeKill (s, loc);
5317         }
5318       else
5319         {
5320                   sRef_kill (s, loc);
5321                 }
5322     }
5323 }
5324
5325 /*
5326 ** kills s and all aliases to s
5327 */
5328
5329 void sRef_killComplete (sRef s, fileloc loc)
5330 {
5331   DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
5332   sRef_aliasSetComplete (sRef_killAux, s, loc);
5333 }
5334
5335 static bool sRef_equivalent (sRef s1, sRef s2)
5336 {
5337   return (sRef_compare (s1, s2) == 0);
5338 }
5339
5340 /*
5341 ** returns an sRef that will not be free'd on function exit.
5342 */
5343
5344 /*@only@*/ sRef sRef_saveCopy (sRef s)
5345 {
5346   sRef ret;
5347
5348   if (sRef_isValid (s))
5349     {
5350       bool old = inFunction;
5351
5352       /*
5353       ** Exit the function scope, so this sRef is not
5354       ** stored in the deallocation table.
5355       */
5356       
5357       inFunction = FALSE;
5358       DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
5359       ret = sRef_copy (s);
5360       DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
5361       inFunction = old;
5362     }
5363   else
5364     {
5365       ret = sRef_undefined;
5366     }
5367
5368   /*@-dependenttrans@*/ 
5369   return ret;
5370   /*@=dependenttrans@*/ 
5371 }
5372
5373 sRef sRef_copy (sRef s)
5374 {
5375   if (sRef_isKindSpecial (s))
5376     {
5377       /*@-retalias@*/
5378       return s; /* don't copy specials */
5379       /*@=retalias@*/
5380     }
5381   
5382   if (sRef_isValid (s))
5383     {
5384       sRef t = sRef_alloc ();
5385
5386       t->kind = s->kind;
5387       t->safe = s->safe;
5388       t->modified = s->modified;
5389       t->type = s->type;
5390
5391             t->info = sinfo_copy (s);
5392       
5393       t->defstate = s->defstate;
5394
5395       t->nullstate = s->nullstate;
5396  
5397       /* start modifications */
5398       t->bufinfo.bufstate = s->bufinfo.bufstate;
5399       t->bufinfo.len = s->bufinfo.len;
5400       t->bufinfo.size = s->bufinfo.size;
5401       /* end modifications */
5402
5403       t->aliaskind = s->aliaskind;
5404       t->oaliaskind = s->oaliaskind;
5405
5406       t->expkind = s->expkind;
5407       t->oexpkind = s->oexpkind;
5408
5409       t->aliasinfo = alinfo_copy (s->aliasinfo);
5410       t->definfo = alinfo_copy (s->definfo);
5411       t->nullinfo = alinfo_copy (s->nullinfo);
5412       t->expinfo = alinfo_copy (s->expinfo);
5413
5414       t->deriv = sRefSet_newDeepCopy (s->deriv);
5415       
5416       return t;
5417     }
5418   else
5419     {
5420       return sRef_undefined;
5421     }
5422 }
5423
5424 /*@notfunction@*/
5425 # define PREDTEST(func,s) \
5426    do { if (sRef_isInvalid (s)) { return FALSE; } \
5427         else { if (sRef_isConj (s)) \
5428                   { return (func (sRef_getConjA (s)) \
5429                             || func (sRef_getConjB (s))); }}} while (FALSE);
5430
5431 bool sRef_isAddress (sRef s)
5432 {
5433   PREDTEST (sRef_isAddress, s);
5434   return (s->kind == SK_ADR);
5435 }
5436           
5437 /*
5438 ** pretty weak... maybe a flag should control this.
5439 */
5440
5441 bool sRef_isThroughArrayFetch (sRef s)
5442 {
5443   if (sRef_isValid (s))
5444     {
5445       sRef tref = s;
5446
5447       do 
5448         {
5449           sRef lt;
5450
5451           if (sRef_isArrayFetch (tref)) 
5452             {
5453                       return TRUE;
5454             }
5455           
5456           lt = sRef_getBase (tref);
5457           tref = lt;
5458         } while (sRef_isValid (tref));
5459     } 
5460
5461   return FALSE;
5462 }
5463
5464 bool sRef_isArrayFetch (sRef s)
5465 {
5466   PREDTEST (sRef_isArrayFetch, s);
5467   return (s->kind == SK_ARRAYFETCH);
5468 }
5469
5470 bool sRef_isMacroParamRef (sRef s)
5471 {
5472   if (context_inMacro () && sRef_isCvar (s))
5473     {
5474       uentry ue = sRef_getUentry (s);
5475       cstring pname = makeParam (uentry_rawName (ue));
5476       uentry mac = usymtab_lookupSafe (pname);
5477
5478       cstring_free (pname);
5479       return (uentry_isValid (mac));
5480     }
5481
5482   return FALSE;
5483 }
5484       
5485 bool sRef_isCvar (sRef s) 
5486 {
5487   PREDTEST (sRef_isCvar, s);
5488   return (s->kind == SK_CVAR);
5489 }
5490
5491 bool sRef_isConst (sRef s) 
5492 {
5493   PREDTEST (sRef_isConst, s);
5494   return (s->kind == SK_CONST);
5495 }
5496
5497 bool sRef_isObject (sRef s) 
5498 {
5499   PREDTEST (sRef_isObject, s);
5500   return (s->kind == SK_OBJECT);
5501 }
5502
5503 bool sRef_isExternal (sRef s) 
5504 {
5505   PREDTEST (sRef_isExternal, s);
5506   return (s->kind == SK_EXTERNAL);
5507 }
5508
5509 static bool sRef_isDerived (sRef s) 
5510 {
5511   PREDTEST (sRef_isDerived, s);
5512   return (s->kind == SK_DERIVED);
5513 }
5514
5515 bool sRef_isField (sRef s)
5516 {
5517   PREDTEST (sRef_isField, s);
5518   return (s->kind == SK_FIELD);
5519 }
5520
5521 static bool sRef_isIndex (sRef s)
5522 {
5523   PREDTEST (sRef_isIndex, s);
5524   return (s->kind == SK_ARRAYFETCH);
5525 }
5526
5527 bool sRef_isAnyParam (sRef s)
5528 {
5529   PREDTEST (sRef_isAnyParam, s);
5530   return (s->kind == SK_PARAM);  
5531 }
5532
5533 bool sRef_isParam (sRef s)
5534 {
5535   PREDTEST (sRef_isParam, s);
5536   return (s->kind == SK_PARAM);
5537 }
5538
5539 bool sRef_isDirectParam (sRef s)
5540 {
5541   PREDTEST (sRef_isDirectParam, s);
5542
5543   return ((s->kind == SK_CVAR) &&
5544           (s->info->cvar->lexlevel == functionScope) &&
5545           (context_inFunction () && 
5546            (s->info->cvar->index <= uentryList_size (context_getParams ()))));
5547 }
5548
5549 bool sRef_isPointer (sRef s)
5550 {
5551   PREDTEST (sRef_isPointer, s);
5552   return (s->kind == SK_PTR);
5553 }
5554
5555 /*
5556 ** returns true if storage referenced by s is visible
5557 */
5558
5559 bool sRef_isReference (sRef s)
5560 {
5561   PREDTEST (sRef_isReference, s);
5562
5563   return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isGlobal (s)
5564           || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
5565 }
5566
5567 bool sRef_isIReference (sRef s)
5568 {
5569   return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
5570           || sRef_isField (s) || sRef_isArrayFetch (s));
5571 }
5572
5573 bool sRef_isGlobal (sRef s)
5574 {
5575   return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
5576 }
5577
5578 bool sRef_isRealGlobal (sRef s)
5579 {
5580   return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
5581 }
5582
5583 bool sRef_isFileStatic (sRef s)
5584 {
5585   return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
5586 }
5587
5588 bool sRef_isAliasCheckedGlobal (sRef s)
5589 {
5590   if (sRef_isGlobal (s))
5591     {
5592       uentry ue = sRef_getUentry (s);
5593
5594       return context_checkAliasGlob (ue);
5595     }
5596   else
5597     {
5598       return FALSE;
5599     }
5600 }
5601
5602 void sRef_free (/*@only@*/ sRef s)
5603 {
5604   if (s != sRef_undefined && s->kind != SK_SPECIAL)
5605     {
5606       alinfo_free (s->expinfo);
5607       alinfo_free (s->aliasinfo);
5608       alinfo_free (s->definfo);
5609       alinfo_free (s->nullinfo);
5610       
5611       sRefSet_free (s->deriv);
5612       s->deriv = sRefSet_undefined;
5613       sinfo_free (s);
5614       
5615       sfree (s); 
5616     }
5617 }
5618
5619 void sRef_setType (sRef s, ctype t)
5620 {
5621   if (sRef_isValid (s))
5622     {
5623       s->type = t;
5624     }
5625 }
5626
5627 void sRef_setTypeFull (sRef s, ctype t)
5628 {
5629   if (sRef_isValid (s))
5630     {
5631       s->type = t;
5632
5633       sRefSet_allElements (s->deriv, current)
5634         {
5635           sRef_setTypeFull (current, ctype_unknown);
5636         } end_sRefSet_allElements ;
5637     }
5638 }
5639
5640 /*@exposed@*/ sRef
5641   sRef_buildField (sRef rec, /*@dependent@*/ cstring f)
5642 {
5643   return (sRef_buildNCField (rec, f)); 
5644 }
5645
5646 static /*@exposed@*/ sRef
5647 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
5648 {
5649   sRefSet_allElements (rec->deriv, sr)
5650     {
5651       if (sRef_isValid (sr))
5652         {
5653           if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
5654             {
5655               return sr;
5656             }
5657         }
5658     } end_sRefSet_allElements;
5659
5660   return sRef_undefined;
5661 }
5662
5663 /*@dependent@*/ /*@observer@*/ sRefSet
5664   sRef_derivedFields (sRef rec)
5665 {
5666   if (sRef_isValid (rec))
5667     {
5668       sRefSet ret;
5669       ret = rec->deriv;
5670       return (ret);
5671     }
5672   else
5673     {
5674       return (sRefSet_undefined);
5675     }
5676 }
5677
5678 static /*@exposed@*/ sRef
5679   sRef_findDerivedPointer (sRef s)
5680 {
5681   if (sRef_isValid (s))
5682     {
5683       sRefSet_realElements (s->deriv, sr)
5684         {
5685           if (sRef_isValid (sr) && sr->kind == SK_PTR)
5686             {
5687               return sr;
5688             }
5689         } end_sRefSet_realElements;
5690     }
5691
5692   return sRef_undefined;
5693 }
5694
5695 bool
5696 sRef_isUnknownArrayFetch (sRef s)
5697 {
5698   return (sRef_isValid (s) 
5699           && s->kind == SK_ARRAYFETCH
5700           && !s->info->arrayfetch->indknown);
5701 }
5702
5703 static /*@exposed@*/ sRef
5704 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
5705 {
5706   
5707   if (isknown) 
5708     {
5709       sRefSet_realElements (s->deriv, sr)
5710         {
5711           if (sRef_isValid (sr)
5712               && sr->kind == SK_ARRAYFETCH
5713               && sr->info->arrayfetch->indknown
5714               && (sr->info->arrayfetch->ind == idx))
5715             {
5716               return sr;
5717             }
5718         } end_sRefSet_realElements;
5719     }
5720   else
5721     {
5722       sRefSet_realElements (s->deriv, sr)
5723         {
5724           if (sRef_isValid (sr)
5725               && sr->kind == SK_ARRAYFETCH
5726               && (!sr->info->arrayfetch->indknown
5727                   || (sr->info->arrayfetch->indknown && 
5728                       sr->info->arrayfetch->ind == 0)))
5729             {
5730               if (sRef_isDead (sr) || sRef_isKept (sr))
5731                 {
5732                   if (dead || context_getFlag (FLG_STRICTUSERELEASED))
5733                     {
5734                       return sr;
5735                     }
5736                 }
5737               else
5738                 {
5739                   return sr;
5740                 }
5741             }
5742         } end_sRefSet_realElements;
5743     }
5744
5745   return sRef_undefined;
5746 }
5747
5748 static /*@exposed@*/ sRef 
5749 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
5750 {
5751   sRef s;
5752
5753   if (sRef_isInvalid (rec))
5754     {
5755       return sRef_undefined;
5756     }
5757       
5758   /*
5759   ** check if the field already has been referenced 
5760   */
5761
5762   s = sRef_findDerivedField (rec, f);
5763   
5764   if (sRef_isValid (s))
5765     {
5766             return s;
5767     }
5768   else
5769     {
5770       ctype ct = ctype_realType (rec->type);
5771
5772       s = sRef_new ();      
5773       s->kind = SK_FIELD;
5774       s->info = (sinfo) dmalloc (sizeof (*s->info));
5775       s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
5776       s->info->field->rec = rec;
5777       s->info->field->field = f; /* doesn't copy f */
5778       
5779       
5780       if (ctype_isKnown (ct) && ctype_isSU (ct))
5781         {
5782           uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
5783         
5784           if (!uentry_isUndefined (ue))
5785             {
5786               s->type = uentry_getType (ue);
5787
5788               if (ctype_isMutable (s->type)
5789                   && rec->aliaskind != AK_STACK 
5790                   && !alkind_isStatic (rec->aliaskind))
5791                 {
5792                   s->aliaskind = rec->aliaskind;
5793                 }
5794               else
5795                 {
5796                   s->aliaskind = AK_UNKNOWN;
5797                 }
5798
5799               if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec) 
5800                   || sRef_isPdefined (rec))
5801                 {
5802                                   sRef_setStateFromUentry (s, ue);
5803                                 }
5804               else
5805                 {
5806                   sRef_setPartsFromUentry (s, ue);
5807                                 }
5808
5809               s->oaliaskind = s->aliaskind;
5810               s->oexpkind = s->expkind;
5811             }
5812           else
5813             {
5814               /*
5815                 Never report this as an error.  It can happen whenever there
5816                 is casting involved.
5817
5818               if (report)
5819                 {
5820                   llcontbug (message ("buildNCField --- no field %s: %q / %s",
5821                                       f, sRef_unparse (s), ctype_unparse (ct)));
5822                 }
5823                 */
5824
5825               return sRef_undefined;
5826             }
5827         }
5828       
5829       if (rec->defstate == SS_DEFINED 
5830           && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
5831         {
5832           s->defstate = SS_DEFINED;
5833         }
5834       else if (rec->defstate == SS_PARTIAL)
5835         {
5836           s->defstate = SS_PARTIAL;
5837         }
5838       else if (rec->defstate == SS_ALLOCATED) 
5839         {
5840           if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
5841             {
5842               s->defstate = SS_ALLOCATED;
5843             }
5844           else
5845             {
5846               s->defstate = SS_UNDEFINED;
5847             }
5848         }
5849       else if (s->defstate == SS_UNKNOWN)
5850         {
5851           s->defstate = rec->defstate;
5852         }
5853       else
5854         {
5855           ; /* no change */
5856         }
5857
5858       if (s->defstate == SS_UNDEFINED)
5859         {
5860           ctype rt = ctype_realType (s->type);
5861           
5862           if (ctype_isArray (rt) || ctype_isSU (rt))
5863             {
5864                       s->defstate = SS_ALLOCATED;
5865             }
5866         }
5867
5868       sRef_addDeriv (rec, s);
5869
5870       if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
5871         {
5872           s->aliaskind = AK_REFS;
5873           s->oaliaskind = AK_REFS;
5874         }
5875
5876             return s;
5877     }
5878 }
5879
5880 bool
5881 sRef_isStackAllocated (sRef s)
5882 {
5883   return (sRef_isValid(s) 
5884           && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
5885 }
5886           
5887 static
5888 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s, 
5889                               /*@notnull@*/ /*@exposed@*/ sRef arr)
5890 {
5891   if (ctype_isRealAP (arr->type))
5892     {
5893       s->type = ctype_baseArrayPtr (arr->type);
5894     }
5895
5896   /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
5897   if (sRef_isAddress (arr)) 
5898     {
5899       sRef t = arr->info->ref;
5900       
5901       if (sRef_isArrayFetch (t))
5902         {
5903           s->info->arrayfetch->arr = t->info->arrayfetch->arr;
5904         }
5905     }
5906   else if (ctype_isRealPointer (arr->type))
5907     {
5908       sRef sp = sRef_findDerivedPointer (arr);
5909
5910       
5911       if (sRef_isValid (sp))
5912         {
5913           
5914           if (ctype_isMutable (s->type))
5915             {
5916               sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
5917
5918                       
5919               s->aliaskind = sp->aliaskind;
5920             }
5921
5922           s->defstate = sp->defstate;
5923
5924           if (s->defstate == SS_DEFINED) 
5925             {
5926               if (!context_getFlag (FLG_STRICTDESTROY))
5927                 {
5928                   s->defstate = SS_PARTIAL;
5929                 }
5930             }
5931
5932           s->nullstate = sp->nullstate;
5933         }
5934       else
5935         {
5936           if (arr->defstate == SS_UNDEFINED)
5937             {
5938               s->defstate = SS_UNUSEABLE;
5939             }
5940           else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
5941             {
5942               s->defstate = SS_UNDEFINED;
5943             }
5944           else
5945             {
5946               if (!context_getFlag (FLG_STRICTDESTROY))
5947                 {
5948                   s->defstate = SS_PARTIAL;
5949                 }
5950               else
5951                 {
5952                   s->defstate = SS_DEFINED;
5953                 }
5954
5955               /*
5956               ** Very weak checking for array elements.
5957               ** Was:
5958               **     s->defstate = arr->defstate;
5959               */
5960             }
5961
5962           sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
5963
5964           if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
5965             {
5966               s->aliaskind = AK_LOCAL;
5967             }
5968           else
5969             {
5970               s->aliaskind = AK_UNKNOWN;
5971             }
5972           
5973           sRef_setTypeState (s);
5974         }
5975     }
5976   else
5977     {
5978       if (arr->defstate == SS_DEFINED)
5979         {
5980           /*
5981           ** Very weak checking for array elements.
5982           ** Was:
5983           **     s->defstate = arr->defstate;
5984           */
5985
5986           if (context_getFlag (FLG_STRICTDESTROY))
5987             {
5988               s->defstate = SS_DEFINED;
5989             }
5990           else
5991             {
5992               s->defstate = SS_PARTIAL;
5993             }
5994         }
5995       else if (arr->defstate == SS_ALLOCATED)
5996         {
5997           if (ctype_isRealArray (s->type))
5998             {
5999               s->defstate = SS_ALLOCATED;
6000             }
6001           else 
6002             {
6003               if (!s->info->arrayfetch->indknown)
6004                 {
6005                   /*
6006                   ** is index is unknown, elements is defined or 
6007                   ** allocated is any element is!
6008                   */
6009                   
6010                   s->defstate = SS_UNDEFINED;
6011                   
6012                   sRefSet_allElements (arr->deriv, sr)
6013                     {
6014                       if (sRef_isValid (sr))
6015                         {
6016                           if (sr->defstate == SS_ALLOCATED)
6017                             {
6018                               s->defstate = SS_ALLOCATED;
6019                             }
6020                           else 
6021                             {
6022                               if (sr->defstate == SS_DEFINED)
6023                                 {
6024                                   if (context_getFlag (FLG_STRICTDESTROY))
6025                                     {
6026                                       s->defstate = SS_DEFINED;
6027                                     }
6028                                   else
6029                                     {
6030                                       s->defstate = SS_PARTIAL;
6031                                     }
6032
6033                                   break;
6034                                 }
6035                             }
6036                         }
6037                     } end_sRefSet_allElements;
6038                   
6039                                 }
6040               else
6041                 {
6042                   s->defstate = SS_UNDEFINED;
6043                 }
6044             }
6045         }
6046       else
6047         {
6048           s->defstate = arr->defstate;
6049         }
6050       
6051       
6052       /*
6053       ** kludgey way to guess where aliaskind applies
6054       */
6055       
6056       if (ctype_isMutable (s->type) 
6057           && !ctype_isPointer (arr->type) 
6058           && !alkind_isStatic (arr->aliaskind)
6059           && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
6060         {
6061           s->aliaskind = arr->aliaskind;
6062         }
6063       else
6064         {
6065           s->aliaskind = AK_UNKNOWN;
6066         }
6067     
6068       sRef_setTypeState (s);
6069     }
6070
6071   if (sRef_isObserver (arr)) 
6072     {
6073       s->expkind = XO_OBSERVER;
6074     }
6075 }  
6076
6077 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
6078 {
6079   sRef s;
6080
6081   if (!sRef_isValid (arr)) {
6082     /*@-nullret@*/ return arr /*@=nullret@*/;
6083   }
6084
6085   if (ctype_isRealPointer (arr->type))
6086     {
6087       (void) sRef_buildPointer (arr); /* do this to define arr! */
6088     }
6089   
6090   s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
6091   
6092   if (sRef_isValid (s))
6093     {
6094       sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
6095       return s;
6096     }
6097   else
6098     {
6099       s = sRef_new ();
6100
6101       s->kind = SK_ARRAYFETCH;
6102       s->info = (sinfo) dmalloc (sizeof (*s->info));
6103       s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6104       s->info->arrayfetch->indknown = FALSE;
6105       s->info->arrayfetch->ind = 0;
6106       s->info->arrayfetch->arr = arr;
6107       sRef_setArrayFetchState (s, arr);
6108       s->oaliaskind = s->aliaskind;
6109       s->oexpkind = s->expkind;
6110
6111       if (!context_inProtectVars ())
6112         {
6113           sRef_addDeriv (arr, s);
6114         }
6115       
6116       return (s);
6117     }
6118 }
6119
6120 /*@exposed@*/ sRef
6121   sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
6122 {
6123   sRef s;
6124
6125   if (!sRef_isValid (arr)) {
6126     /*@-nullret@*/ return arr /*@=nullret@*/;
6127   }
6128
6129   if (ctype_isRealPointer (arr->type))
6130     {
6131        (void) sRef_buildPointer (arr); /* do this to define arr! */
6132     }
6133
6134   s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
6135       
6136   if (sRef_isValid (s))
6137     {
6138       sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);      
6139       return s;
6140     }
6141   else
6142     {
6143       s = sRef_new ();
6144       
6145       s->kind = SK_ARRAYFETCH;
6146       s->info = (sinfo) dmalloc (sizeof (*s->info));
6147       s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
6148       s->info->arrayfetch->arr = arr;
6149       s->info->arrayfetch->indknown = TRUE;
6150       s->info->arrayfetch->ind = i;
6151       
6152       sRef_setArrayFetchState (s, arr);
6153       
6154       s->oaliaskind = s->aliaskind;
6155       s->oexpkind = s->expkind;
6156       sRef_addDeriv (arr, s);
6157
6158       return (s);
6159     }
6160 }
6161
6162 /*
6163 ** sets everything except for defstate
6164 */
6165
6166 static void
6167 sRef_setPartsFromUentry (sRef s, uentry ue)
6168 {
6169     
6170   llassert (sRef_isValid (s));
6171
6172   s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6173   s->oaliaskind = s->aliaskind;
6174
6175   if (s->expkind == XO_UNKNOWN)
6176     {
6177       s->expkind = uentry_getExpKind (ue);
6178     }
6179
6180   s->oexpkind = s->expkind;
6181
6182   if (s->nullstate == NS_UNKNOWN)
6183     {
6184       s->nullstate = sRef_getNullState (uentry_getSref (ue));
6185     }
6186
6187   if (s->aliaskind == AK_IMPONLY 
6188       && (sRef_isExposed (s) || sRef_isObserver (s)))
6189     {
6190       s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
6191     }
6192
6193 }
6194
6195 static void
6196 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
6197 {
6198   llassert (sRef_isValid (s));
6199   
6200   sRef_setPartsFromUentry (s, ue);
6201
6202   s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
6203   s->oaliaskind = s->aliaskind;
6204
6205   if (s->expkind == XO_UNKNOWN)
6206     {
6207       s->expkind = uentry_getExpKind (ue);
6208     }
6209
6210   s->oexpkind = s->expkind;
6211 }
6212
6213 void
6214 sRef_setStateFromUentry (sRef s, uentry ue)
6215 {
6216   sstate defstate;
6217
6218   llassert (sRef_isValid (s));
6219   
6220   sRef_setPartsFromUentry (s, ue);
6221
6222   defstate = uentry_getDefState (ue);
6223
6224   if (sstate_isKnown (defstate))
6225     {
6226       s->defstate = defstate;
6227     }
6228   else
6229     {
6230       ;
6231     }
6232 }
6233
6234 /*@exposed@*/ sRef
6235   sRef_buildPointer (/*@exposed@*/ sRef t)
6236 {
6237   DPRINTF (("build pointer: %s", sRef_unparse (t)));
6238
6239   if (sRef_isInvalid (t)) return sRef_undefined;
6240
6241   if (sRef_isAddress (t))
6242     {
6243       DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
6244       return (t->info->ref);
6245     }
6246   else
6247     {
6248       sRef s = sRef_findDerivedPointer (t);
6249
6250       DPRINTF (("find derived: %s", sRef_unparse (s)));
6251
6252       if (sRef_isValid (s))
6253         {
6254           
6255           sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
6256           s->oaliaskind = s->aliaskind;
6257           s->oexpkind = s->expkind;
6258
6259           return s;
6260         }
6261       else
6262         {
6263           s = sRef_constructPointerAux (t);
6264           
6265           DPRINTF (("construct: %s", sRef_unparse (s)));
6266
6267           if (sRef_isValid (s))
6268             {
6269               sRef_addDeriv (t, s);
6270
6271               s->oaliaskind = s->aliaskind;
6272               s->oexpkind = s->expkind;
6273             }
6274           
6275           return s;
6276         }
6277     }
6278 }
6279
6280 /*@exposed@*/ sRef
6281 sRef_constructPointer (sRef t)
6282    /*@modifies t@*/
6283 {
6284   return sRef_buildPointer (t);
6285 }
6286
6287 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
6288 {
6289   if (sRef_isValid (t))
6290     {
6291       sRef s;
6292       
6293       /*
6294       ** if there is a derived t[?], return that.  Otherwise, *t.
6295       */
6296       
6297             
6298       s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
6299       
6300       if (sRef_isValid (s))
6301         {
6302                   return s;
6303         }
6304       else
6305         {
6306           sRef ret = sRef_constructPointer (t);
6307
6308           /*
6309           ** This is necessary to prevent infinite depth
6310           ** in checking complete destruction.  
6311           */
6312
6313           
6314           if (isdead)
6315             {
6316               /* ret->defstate = SS_UNKNOWN;  */
6317               return ret; 
6318             }
6319           else
6320             {
6321               return ret;
6322             }
6323         }
6324     }
6325   else
6326     {
6327       return sRef_undefined;
6328     }
6329 }
6330
6331 sRef sRef_constructDeref (sRef t)
6332 {
6333   return sRef_constructDerefAux (t, FALSE);
6334 }
6335
6336 sRef sRef_constructDeadDeref (sRef t)
6337 {
6338   return sRef_constructDerefAux (t, TRUE);
6339 }
6340
6341 static sRef
6342 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
6343 {
6344   sRef s = sRef_new ();
6345   ctype rt = t->type;
6346   ctype st;
6347   
6348   s->kind = SK_PTR;
6349   s->info = (sinfo) dmalloc (sizeof (*s->info));
6350   s->info->ref = t;
6351   
6352   if (ctype_isRealAP (rt))
6353     {
6354       s->type = ctype_baseArrayPtr (rt);
6355     }
6356   
6357   st = ctype_realType (s->type);
6358   
6359     
6360   if (t->defstate == SS_UNDEFINED)
6361     {
6362       s->defstate = SS_UNUSEABLE;
6363     }
6364   else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
6365     {
6366       s->defstate = SS_UNDEFINED;
6367     }
6368   else
6369     {
6370       s->defstate = t->defstate;
6371     }
6372   
6373   if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
6374     {
6375       s->aliaskind = AK_LOCAL;
6376     }
6377   else
6378     {
6379       s->aliaskind = AK_UNKNOWN;
6380     }
6381   
6382   sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
6383   sRef_setTypeState (s);
6384   
6385   s->oaliaskind = s->aliaskind;
6386   s->oexpkind = s->expkind;
6387
6388   return s;
6389 }
6390
6391 bool sRef_hasDerived (sRef s)
6392 {
6393   return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
6394 }
6395
6396 void
6397 sRef_clearDerived (sRef s)
6398 {
6399   if (sRef_isValid (s))
6400     {
6401             sRefSet_clear (s->deriv); 
6402     }
6403 }
6404
6405 void
6406 sRef_clearDerivedComplete (sRef s)
6407 {
6408   
6409   if (sRef_isValid (s))
6410     {
6411       sRef base = sRef_getBaseSafe (s);
6412
6413       while (sRef_isValid (base))
6414         {
6415           sRefSet_clear (base->deriv); 
6416           base = sRef_getBaseSafe (base);
6417         }
6418
6419       sRefSet_clear (s->deriv); 
6420     }
6421 }
6422
6423 /*@exposed@*/ sRef
6424 sRef_makePointer (sRef s)
6425    /*@modifies s@*/
6426 {
6427   sRef res = sRef_buildPointer (s); 
6428
6429   DPRINTF (("Res: %s", sRef_unparse (res)));
6430   return res;
6431 }
6432
6433 /*
6434 ** &a[] => a (this is for out params)
6435 */
6436
6437 /*@exposed@*/ sRef
6438 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
6439 {
6440   
6441   if (sRef_isAddress (arr))
6442     {
6443             return (arr->info->ref);
6444     }
6445   else
6446     {
6447       return (sRef_buildArrayFetch (arr));
6448     }
6449 }
6450
6451 /*@exposed@*/ sRef
6452 sRef_makeArrayFetch (sRef arr)
6453 {
6454   return (sRef_buildArrayFetch (arr));
6455 }
6456
6457 /*@exposed@*/ sRef
6458 sRef_makeArrayFetchKnown (sRef arr, int i)
6459 {
6460   return (sRef_buildArrayFetchKnown (arr, i));
6461 }
6462
6463 /*@exposed@*/ sRef
6464 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
6465 {
6466   sRef ret;
6467   ret = sRef_buildField (rec, f);
6468   return ret;
6469 }
6470
6471 /*@exposed@*/ sRef
6472 sRef_makeNCField (sRef rec, /*@dependent@*/ cstring f)
6473 {
6474     return (sRef_buildNCField (rec, f));
6475 }
6476
6477 /*@only@*/ cstring
6478 sRef_unparseKindName (sRef s)
6479 {
6480   cstring result;
6481
6482   if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6483
6484   s = sRef_fixConj (s);
6485
6486   switch (s->kind)
6487     {
6488     case SK_CVAR: 
6489       if (sRef_isLocalVar (s)) 
6490         {
6491           result = cstring_makeLiteral ("Variable");
6492         }
6493       else
6494         {
6495           result = cstring_makeLiteral ("Undef global");
6496         }
6497       break;
6498     case SK_PARAM:
6499       result = cstring_makeLiteral ("Out parameter");
6500       break;
6501     case SK_ARRAYFETCH:
6502       if (sRef_isAnyParam (s->info->arrayfetch->arr)) 
6503         {
6504           result = cstring_makeLiteral ("Out parameter");
6505         }
6506       else if (sRef_isIndexKnown (s))
6507         {
6508           result = cstring_makeLiteral ("Array element");
6509         }
6510       else
6511         {
6512           result = cstring_makeLiteral ("Value");
6513         }
6514       break;
6515     case SK_PTR:
6516       if (sRef_isAnyParam (s->info->ref)) 
6517         {
6518           result = cstring_makeLiteral ("Out parameter");
6519         }
6520       else
6521         {
6522           result = cstring_makeLiteral ("Value");
6523         }
6524       break;
6525     case SK_ADR:
6526       result = cstring_makeLiteral ("Value");
6527       break;
6528     case SK_FIELD:
6529       result = cstring_makeLiteral ("Field");
6530       break;
6531     case SK_OBJECT:
6532       result = cstring_makeLiteral ("Object");
6533       break;
6534     case SK_UNCONSTRAINED:
6535       result = cstring_makeLiteral ("<anything>");
6536       break;
6537     case SK_RESULT:
6538     case SK_SPECIAL:
6539     case SK_UNKNOWN:
6540     case SK_EXTERNAL:
6541     case SK_DERIVED:
6542     case SK_CONST:
6543     case SK_TYPE:
6544       result = cstring_makeLiteral ("<unknown>");
6545       break;
6546     case SK_CONJ:
6547       result = cstring_makeLiteral ("<conj>");
6548       break;
6549     case SK_NEW:
6550       result = cstring_makeLiteral ("Storage");
6551       break;
6552     }
6553   
6554   return result;
6555 }
6556
6557 /*@only@*/ cstring
6558 sRef_unparseKindNamePlain (sRef s)
6559 {
6560   cstring result;
6561
6562   if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
6563
6564   s = sRef_fixConj (s);
6565
6566   switch (s->kind)
6567     {
6568     case SK_CVAR: 
6569       if (sRef_isLocalVar (s)) 
6570         {
6571           result = cstring_makeLiteral ("Variable");
6572         }
6573       else 
6574         {
6575           result = cstring_makeLiteral ("Global");
6576         }
6577       break;
6578     case SK_PARAM:
6579       result = cstring_makeLiteral ("Parameter");
6580       break;
6581     case SK_ARRAYFETCH:
6582       if (sRef_isAnyParam (s->info->arrayfetch->arr)) 
6583         {
6584           result = cstring_makeLiteral ("Parameter");
6585         }
6586       else if (sRef_isIndexKnown (s))
6587         {
6588           result = cstring_makeLiteral ("Array element");
6589         }
6590       else 
6591         {
6592           result = cstring_makeLiteral ("Value");
6593         }
6594       break;
6595     case SK_PTR:
6596       if (sRef_isAnyParam (s->info->ref))
6597         {
6598           result = cstring_makeLiteral ("Parameter");
6599         }
6600       else
6601         {
6602           result = cstring_makeLiteral ("Value");
6603         }
6604       break;
6605     case SK_ADR:
6606       result = cstring_makeLiteral ("Value");
6607       break;
6608     case SK_FIELD:
6609       result = cstring_makeLiteral ("Field");
6610       break;
6611     case SK_OBJECT:
6612       result = cstring_makeLiteral ("Object");
6613       break;
6614     case SK_NEW:
6615       result = cstring_makeLiteral ("Storage");
6616       break;
6617     case SK_UNCONSTRAINED:
6618       result = cstring_makeLiteral ("<anything>");
6619       break;
6620     case SK_RESULT:
6621     case SK_TYPE:
6622     case SK_CONST:
6623     case SK_EXTERNAL:
6624     case SK_DERIVED:
6625     case SK_UNKNOWN:
6626     case SK_SPECIAL:
6627       result = cstring_makeLiteral ("<unknown>");
6628       break;
6629     case SK_CONJ:
6630       result = cstring_makeLiteral ("<conj>");
6631       break;
6632     }
6633   
6634   return result;
6635 }
6636
6637 /*
6638 ** s1 <- s2
6639 */
6640
6641 void
6642 sRef_copyState (sRef s1, sRef s2)
6643 {
6644   if (sRef_isValid (s1) && sRef_isValid (s2))
6645     {
6646       s1->defstate = s2->defstate;
6647       
6648       s1->nullstate = s2->nullstate;
6649       s1->nullinfo = alinfo_update (s1->nullinfo, s2->nullinfo);
6650       
6651       /* start modifications */
6652       s1->bufinfo.bufstate = s2->bufinfo.bufstate;
6653       s1->bufinfo.len = s2->bufinfo.len;
6654       s1->bufinfo.size = s2->bufinfo.size;
6655       /* end modifications */
6656
6657       s1->aliaskind = s2->aliaskind;
6658       s1->aliasinfo = alinfo_update (s1->aliasinfo, s2->aliasinfo);
6659
6660       s1->expkind = s2->expkind;
6661       s1->expinfo = alinfo_update (s1->expinfo, s2->expinfo);
6662
6663       s1->safe = s2->safe;
6664           }
6665 }
6666
6667 sRef
6668 sRef_makeNew (ctype ct, sRef t, cstring name)
6669 {
6670   sRef s = sRef_new ();
6671
6672   s->kind = SK_NEW;
6673   s->type = ct;
6674
6675   llassert (sRef_isValid (t));
6676   s->defstate = t->defstate;
6677
6678   s->aliaskind = t->aliaskind;
6679   s->oaliaskind = s->aliaskind;
6680
6681   s->nullstate = t->nullstate;
6682
6683   s->expkind = t->expkind;
6684   s->oexpkind = s->expkind;
6685
6686   s->info = (sinfo) dmalloc (sizeof (*s->info));
6687   s->info->fname = name;
6688
6689   /* start modifications */
6690   s->bufinfo.bufstate = t->bufinfo.bufstate;
6691   /* end modifications */
6692
6693     return s;
6694 }
6695
6696 sRef
6697 sRef_makeType (ctype ct)
6698 {
6699   sRef s = sRef_new ();
6700   
6701   s->kind = SK_TYPE;
6702   s->type = ct;
6703
6704   s->defstate = SS_UNKNOWN; 
6705   s->aliaskind = AK_UNKNOWN;
6706   s->nullstate = NS_UNKNOWN;
6707   /* start modification */
6708   s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
6709   /* end modification */
6710
6711     
6712   if (ctype_isUA (ct))
6713     {
6714       typeId uid = ctype_typeId (ct);
6715       uentry ue = usymtab_getTypeEntrySafe (uid);
6716
6717       if (uentry_isValid (ue))
6718         {
6719           sRef_mergeStateQuiet (s, uentry_getSref (ue));
6720         }
6721     }
6722
6723     s->oaliaskind = s->aliaskind;
6724   s->oexpkind = s->expkind;
6725
6726   return s;
6727 }
6728
6729 sRef
6730 sRef_makeConst (ctype ct)
6731 {
6732   sRef s = sRef_new ();
6733   
6734   s->kind = SK_CONST;
6735   s->type = ct;
6736
6737   s->defstate = SS_UNKNOWN;
6738   s->aliaskind = AK_UNKNOWN;
6739   s->nullstate = NS_UNKNOWN;
6740   /* start modification */
6741   s->bufinfo.bufstate = BB_NULLTERMINATED;
6742   /* end modification */
6743
6744   
6745   if (ctype_isUA (ct))
6746     {
6747       typeId uid = ctype_typeId (ct);
6748       uentry te = usymtab_getTypeEntrySafe (uid);
6749       
6750       if (uentry_isValid (te))
6751         {
6752           sRef_mergeStateQuiet (s, uentry_getSref (te));
6753         }
6754     }
6755
6756   
6757   s->oaliaskind = s->aliaskind;
6758   s->oexpkind = s->expkind;
6759
6760   return s;
6761 }
6762
6763 bool sRef_hasName (sRef s)
6764 {
6765   if (sRef_isInvalid (s))
6766     {
6767       return (FALSE);
6768     }
6769
6770   switch (s->kind)
6771     {
6772     case SK_CVAR:
6773       {
6774         uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
6775                                          s->info->cvar->index);
6776         return (uentry_hasName (u));
6777       }
6778     case SK_PARAM:
6779       {
6780         uentry u = uentryList_getN (context_getParams (), 
6781                                     s->info->paramno);
6782
6783         return (uentry_hasName (u));
6784       }
6785     default:
6786       return TRUE;
6787     }
6788 }
6789
6790 bool sRef_sameObject (sRef s1, sRef s2)
6791 {
6792   return sRef_sameName(s1, s2);
6793 }
6794 bool
6795 sRef_sameName (sRef s1, sRef s2)
6796 {
6797   if (sRef_isInvalid (s1))
6798     {
6799       return sRef_isInvalid (s2);
6800     }
6801
6802   if (sRef_isInvalid (s2))
6803     {
6804       return (FALSE);
6805     }
6806
6807   switch (s1->kind)
6808     {
6809     case SK_CVAR:
6810       if (s2->kind == SK_CVAR)
6811         {
6812           return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
6813                   && s1->info->cvar->index == s2->info->cvar->index);
6814         }
6815       else if (s2->kind == SK_PARAM)
6816         {
6817           if (context_inFunctionLike ())
6818             {
6819               uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
6820                                                s1->info->cvar->index);
6821               uentry u2 = uentryList_getN (context_getParams (), 
6822                                            s2->info->paramno);
6823           
6824               return (cstring_equalFree (uentry_getName (u1),
6825                                          uentry_getName (u2)));
6826             }
6827           else 
6828             {
6829               return FALSE;
6830             }
6831         }
6832       else
6833         {
6834           return FALSE;
6835         }
6836     case SK_PARAM:
6837       {
6838         if (s2->kind == SK_PARAM)
6839           {
6840             return (s1->info->paramno == s2->info->paramno);
6841           }
6842         else if (s2->kind == SK_CVAR)
6843           {
6844             if (context_inFunctionLike ())
6845               {
6846                 uentry u1 = uentryList_getN (context_getParams (), 
6847                                              s1->info->paramno);
6848                 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
6849                                                  s2->info->cvar->index);
6850
6851                 
6852                 return (cstring_equalFree (uentry_getName (u1),
6853                                            uentry_getName (u2)));
6854               }
6855             else 
6856               {
6857                 return FALSE;
6858               }
6859           }
6860         else
6861           {
6862             return FALSE;
6863           }
6864       }
6865
6866     case SK_UNCONSTRAINED:
6867       return FALSE;
6868
6869     case SK_ARRAYFETCH:
6870       if (s2->kind == SK_ARRAYFETCH)
6871         {
6872           if (bool_equal (s1->info->arrayfetch->indknown,
6873                           s2->info->arrayfetch->indknown))
6874             {
6875               if (!s1->info->arrayfetch->indknown 
6876                   || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
6877                 {
6878                   return sRef_sameName (s1->info->arrayfetch->arr,
6879                                         s2->info->arrayfetch->arr);
6880                 }
6881             }
6882         }
6883
6884       return FALSE;
6885     case SK_FIELD:
6886       if (s2->kind == SK_FIELD)
6887         {
6888           if (cstring_equal (s1->info->field->field,
6889                              s2->info->field->field))
6890             {
6891               return sRef_sameName (s1->info->field->rec,
6892                                     s2->info->field->rec);
6893             }
6894
6895         }
6896       return FALSE;
6897     case SK_PTR:
6898     case SK_ADR:
6899     case SK_DERIVED:
6900     case SK_EXTERNAL:
6901       if (s2->kind == s1->kind)
6902         {
6903           return sRef_sameName (s1->info->ref,
6904                                 s2->info->ref);
6905         }
6906
6907       return FALSE;
6908     case SK_OBJECT:
6909       return FALSE;
6910     case SK_CONJ:
6911       return sRef_sameName (sRef_getConjA (s1), s2);
6912     case SK_NEW:
6913       return FALSE;
6914     case SK_UNKNOWN:
6915       return (s2->kind == SK_UNKNOWN);
6916     case SK_TYPE:
6917     case SK_CONST:
6918       if (s2->kind == s1->kind)
6919         {
6920           return (ctype_equal (s1->type, s2->type));
6921         }
6922       
6923       return FALSE;
6924     case SK_SPECIAL:
6925       if (s2->kind == SK_SPECIAL)
6926         {
6927           return (s1->info->spec == s2->info->spec);
6928         }
6929       return FALSE;
6930     case SK_RESULT:
6931       return (s2->kind == SK_RESULT);
6932     default:
6933       return FALSE;
6934     }
6935   BADEXIT;
6936 }
6937                 
6938 sRef
6939 sRef_fixOuterRef (/*@returned@*/ sRef s)
6940 {
6941   sRef root = sRef_getRootBase (s);
6942
6943   if (sRef_isCvar (root))
6944     {
6945       uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel, 
6946                                        root->info->cvar->index);
6947
6948       if (uentry_isValid (ue))
6949         {
6950           sRef uref = uentry_getSref (ue);
6951           sRef sr = sRef_fixBase (s, uref);
6952
6953           return (sr);
6954         }
6955       else
6956         {
6957           llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
6958           return (s);
6959         }
6960     }
6961
6962   return (s);
6963 }
6964
6965 void
6966 sRef_storeState (sRef s)
6967 {
6968   if (sRef_isInvalid (s)) return;
6969
6970   s->oaliaskind = s->aliaskind;
6971   s->oexpkind = s->expkind;
6972 }
6973   
6974 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
6975 {
6976   sRef_resetState (s);
6977 }
6978
6979 void
6980 sRef_resetState (sRef s)
6981 {
6982   bool changed = FALSE;
6983   if (sRef_isInvalid (s)) return;
6984
6985   
6986   if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
6987     {
6988       /*
6989       ** killref is used in a kludgey way, to save having to add
6990       ** another alias kind (see usymtab_handleParams)
6991       */
6992  
6993       if (s->expkind != s->oexpkind)
6994         {
6995           changed = TRUE;
6996           s->expkind = s->oexpkind;
6997         }
6998     }
6999   else
7000     {
7001       if (s->expkind != s->oexpkind)
7002         {
7003           changed = TRUE;
7004           s->expkind = s->oexpkind;       
7005         }
7006
7007       if (s->aliaskind != s->oaliaskind
7008           && s->aliaskind != AK_REFCOUNTED
7009           && s->aliaskind != AK_REFS)
7010         {
7011           changed = TRUE;
7012           s->aliaskind = s->oaliaskind;
7013                 }
7014     }
7015
7016   if (changed)
7017     {
7018       sRef_clearDerived (s);
7019     }
7020   
7021   }
7022
7023 void
7024 sRef_resetStateComplete (sRef s)
7025 {
7026   sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
7027 }
7028
7029 /*@exposed@*/ sRef
7030 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
7031 {
7032   sRef tmp = sRef_undefined;
7033   sRef ret;
7034
7035   if (sRef_isInvalid (s)) return s;
7036   if (sRef_isInvalid (base)) return base;
7037
7038   switch (s->kind)
7039     {
7040     case SK_RESULT:
7041     case SK_PARAM:
7042     case SK_CVAR:
7043       ret = base;
7044       break;
7045     case SK_ARRAYFETCH:
7046       tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
7047
7048       if (s->info->arrayfetch->indknown)
7049         {
7050           ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
7051         }
7052       else
7053         {
7054           ret = sRef_makeArrayFetch (tmp);
7055         }
7056       break;
7057     case SK_FIELD:
7058       tmp = sRef_fixBase (s->info->field->rec, base);
7059       ret = sRef_buildNCField (tmp, s->info->field->field);
7060       break;
7061     case SK_PTR:
7062       tmp = sRef_fixBase (s->info->ref, base);
7063       ret = sRef_makePointer (tmp);
7064       break;
7065     case SK_ADR:
7066       tmp = sRef_fixBase (s->info->ref, base);
7067       ret = sRef_makeAddress (tmp);
7068       break;
7069     case SK_CONJ:
7070       {
7071         sRef tmpb;
7072
7073         tmp = sRef_fixBase (s->info->conj->a, base);
7074         tmpb = sRef_fixBase (s->info->conj->b, base);
7075
7076         ret = sRef_makeConj (tmp, tmpb);
7077         break;
7078       }
7079       BADDEFAULT;
7080     }
7081
7082   return ret;
7083 }
7084
7085 static /*@exposed@*/ sRef 
7086 sRef_fixDirectBase (sRef s, sRef base)
7087 {
7088   sRef ret;
7089
7090   
7091   if (sRef_isInvalid (s))
7092     {
7093             return sRef_undefined;
7094     }
7095
7096   switch (s->kind)
7097     {
7098     case SK_ARRAYFETCH:
7099       if (s->info->arrayfetch->indknown)
7100         {
7101           ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
7102         }
7103       else
7104         {
7105           ret = sRef_makeArrayFetch (base);
7106         }
7107       break;
7108     case SK_FIELD:
7109       ret = sRef_buildNCField (base, s->info->field->field);
7110       break;
7111     case SK_PTR:
7112             ret = sRef_makePointer (base);
7113             break;
7114     case SK_ADR:
7115       ret = sRef_makeAddress (base);
7116       break;
7117     case SK_CONJ:
7118       {
7119         sRef tmpa, tmpb;
7120
7121         tmpa = sRef_fixDirectBase (s->info->conj->a, base);
7122         tmpb = sRef_fixDirectBase (s->info->conj->b, base);
7123
7124         ret = sRef_makeConj (tmpa, tmpb);
7125         break;
7126       }
7127       BADDEFAULT;
7128     }
7129
7130     sRef_copyState (ret, s);
7131     return ret;
7132 }
7133
7134 bool
7135 sRef_isAllocIndexRef (sRef s)
7136 {
7137   return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown) 
7138           && sRef_isAllocated (s->info->arrayfetch->arr));
7139 }
7140
7141 void
7142 sRef_showRefLost (sRef s)
7143 {
7144   if (sRef_hasAliasInfoLoc (s))
7145     {
7146       llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
7147                 sRef_getAliasInfoLoc (s));
7148     }
7149 }
7150
7151 void
7152 sRef_showRefKilled (sRef s)
7153 {
7154   if (sRef_hasStateInfoLoc (s))
7155     {
7156       llgenindentmsg (message ("Storage %q released", 
7157                                sRef_unparse (s)), sRef_getStateInfoLoc (s));
7158     }
7159 }
7160
7161 void
7162 sRef_showStateInconsistent (sRef s)
7163 {
7164   if (sRef_hasStateInfoLoc (s))
7165     {
7166       llgenindentmsg
7167         (message ("Storage %qbecomes inconsistent (released on one branch)",
7168                   sRef_unparseOpt (s)), 
7169          sRef_getStateInfoLoc (s));
7170     }
7171 }
7172
7173 void
7174 sRef_showStateInfo (sRef s)
7175 {
7176   if (sRef_hasStateInfoLoc (s))
7177     {
7178       if (s->defstate == SS_DEAD)
7179         {
7180           llgenindentmsg 
7181             (message ("Storage %qis released", sRef_unparseOpt (s)),
7182              sRef_getStateInfoLoc (s));
7183         }
7184       else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
7185         {
7186           llgenindentmsg 
7187             (message ("Storage %qis %s", sRef_unparseOpt (s), 
7188                       sstate_unparse (s->defstate)),
7189              sRef_getStateInfoLoc (s));
7190         }
7191       else if (s->defstate == SS_UNUSEABLE)
7192         {
7193           llgenindentmsg 
7194             (message ("Storage %qbecomes inconsistent (clauses merge with"
7195                       "%qreleased on one branch)",
7196                       sRef_unparseOpt (s), 
7197                       sRef_unparseOpt (s)),
7198              sRef_getStateInfoLoc (s));
7199         }
7200       else 
7201         {
7202           llgenindentmsg (message ("Storage %qbecomes %s", 
7203                                    sRef_unparseOpt (s), 
7204                                    sstate_unparse (s->defstate)),
7205                           sRef_getStateInfoLoc (s));
7206         }
7207     }
7208 }
7209
7210 void
7211 sRef_showExpInfo (sRef s)
7212 {
7213   if (sRef_hasExpInfoLoc (s))
7214     {
7215       llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s), 
7216                                exkind_unparse (s->expkind)),
7217                       sRef_getExpInfoLoc (s));
7218     }
7219 }
7220
7221 void
7222 sRef_showNullInfo (sRef s)
7223 {
7224   if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
7225     {
7226       switch (s->nullstate)
7227         {
7228         case NS_CONSTNULL:
7229           {
7230             fileloc loc = sRef_getNullInfoLoc (s);
7231             
7232             if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7233               {
7234                 llgenindentmsg 
7235                   (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7236                    loc);
7237               }
7238             break;
7239           }
7240         case NS_DEFNULL:
7241           {
7242             fileloc loc = sRef_getNullInfoLoc (s);
7243             
7244             if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
7245               {
7246                 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
7247                                 loc);
7248               }
7249             break;
7250           }
7251         case NS_ABSNULL:
7252         case NS_POSNULL:
7253           llgenindentmsg
7254             (message ("Storage %qmay become null", sRef_unparseOpt (s)),
7255              sRef_getNullInfoLoc (s));
7256           break;
7257         case NS_NOTNULL:
7258         case NS_MNOTNULL:
7259           llgenindentmsg
7260             (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
7261              sRef_getNullInfoLoc (s));
7262           break;
7263         case NS_UNKNOWN:
7264           llgenindentmsg
7265             (message ("Storage %qnull state becomes unknown",
7266                       sRef_unparseOpt (s)),
7267              sRef_getNullInfoLoc (s));
7268           break;
7269
7270         case NS_ERROR:
7271           BADBRANCHCONT;
7272           break;
7273
7274         default:
7275           llgenindentmsg
7276             (message ("<error case> Storage %q becomes %s",
7277                       sRef_unparse (s), 
7278                       nstate_unparse (s->nullstate)),
7279              sRef_getNullInfoLoc (s));
7280           
7281           break;
7282         }
7283     }
7284 }
7285
7286 void
7287 sRef_showAliasInfo (sRef s)
7288 {
7289   if (sRef_hasAliasInfoLoc (s))
7290     {
7291       if (sRef_isFresh (s))
7292         {
7293           llgenindentmsg 
7294             (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
7295              sRef_getAliasInfoLoc (s));
7296         }
7297       else 
7298         {
7299           if (!sRef_isRefCounted (s))
7300             {
7301               llgenindentmsg 
7302                 (message ("Storage %qbecomes %s", 
7303                           sRef_unparseOpt (s),
7304                           alkind_unparse (sRef_getAliasKind (s))),
7305                  sRef_getAliasInfoLoc (s));
7306             }
7307         }
7308     }
7309 }
7310
7311 void
7312 sRef_mergeNullState (sRef s, nstate n)
7313 {
7314   if (sRef_isValid (s))
7315     {
7316       nstate old;
7317       
7318       old = s->nullstate;
7319       
7320       if (n != old && n != NS_UNKNOWN)
7321         {
7322                   
7323           s->nullstate = n;
7324           s->nullinfo = alinfo_updateLoc (s->nullinfo, g_currentloc);
7325         }
7326     }
7327   else
7328     {
7329       llbuglit ("sRef_mergeNullState: invalid");
7330     }
7331 }
7332
7333 bool
7334 sRef_possiblyNull (sRef s)
7335 {
7336   if (sRef_isValid (s))
7337     {
7338       if (s->nullstate == NS_ABSNULL)
7339         {
7340           ctype rct = ctype_realType (s->type);
7341
7342           if (ctype_isAbstract (rct))
7343             {
7344               return FALSE;
7345             }
7346           else
7347             {
7348               if (ctype_isUser (rct))
7349                 {
7350                   uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7351                   
7352                   return (nstate_possiblyNull
7353                           (sRef_getNullState (uentry_getSref (ue))));
7354                 }
7355               else
7356                 {
7357                   return FALSE;
7358                 }
7359             }
7360         }
7361       else
7362         {
7363           return nstate_possiblyNull (s->nullstate);
7364         }
7365     }
7366
7367   return FALSE;
7368 }
7369
7370 cstring
7371 sRef_getScopeName (sRef s)
7372 {
7373   sRef base = sRef_getRootBase (s);
7374
7375   if (sRef_isRealGlobal (base))
7376     {
7377       return (cstring_makeLiteralTemp ("Global"));
7378     }
7379   else if (sRef_isFileStatic (base))
7380     {
7381       return (cstring_makeLiteralTemp ("Static"));
7382     }
7383   else
7384     {
7385       return (cstring_makeLiteralTemp ("Local"));
7386     }
7387 }
7388
7389 cstring
7390 sRef_unparseScope (sRef s)
7391 {
7392   sRef base = sRef_getRootBase (s);
7393
7394   if (sRef_isRealGlobal (base))
7395     {
7396       return (cstring_makeLiteralTemp ("global"));
7397     }
7398   else if (sRef_isFileStatic (base))
7399     {
7400       return (cstring_makeLiteralTemp ("file static"));
7401     }
7402   else
7403     {
7404       BADEXIT;
7405     }
7406 }
7407
7408 int
7409 sRef_getScope (sRef s)
7410 {
7411   llassert (sRef_isValid (s));
7412
7413   if (sRef_isCvar (s))
7414     {
7415       return s->info->cvar->lexlevel;
7416     }
7417   else if (sRef_isParam (s))
7418     {
7419       return paramsScope;
7420     }
7421   else
7422     {
7423       return fileScope;
7424     }
7425 }
7426
7427 bool
7428 sRef_isDead (sRef s)
7429 {
7430   return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
7431 }
7432
7433 bool
7434 sRef_isDeadStorage (sRef s)
7435 {
7436   if (sRef_isValid (s))
7437     {
7438       if (s->defstate == SS_DEAD
7439           || s->defstate == SS_UNUSEABLE
7440           || s->defstate == SS_UNDEFINED
7441           || s->defstate == SS_UNKNOWN)
7442         {
7443           return TRUE;
7444         }
7445       else 
7446         {
7447           return (sRef_isDefinitelyNull (s));
7448         }
7449     }
7450   else
7451     {
7452       return FALSE;
7453     }
7454 }
7455
7456 bool
7457 sRef_isPossiblyDead (sRef s)
7458 {
7459   return (sRef_isValid (s) && s->defstate == SS_HOFFA);
7460 }
7461
7462 bool sRef_isStateLive (sRef s)
7463 {
7464   if (sRef_isValid (s))
7465     {
7466       sstate ds = s->defstate;
7467
7468       return (!(ds == SS_UNDEFINED 
7469                 || ds == SS_DEAD
7470                 || ds == SS_UNUSEABLE
7471                 || ds == SS_HOFFA));
7472     }
7473   else
7474     {
7475       return FALSE;
7476     }
7477 }
7478
7479
7480 bool sRef_isStateUndefined (sRef s)
7481 {
7482   return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
7483 }
7484
7485 bool sRef_isJustAllocated (sRef s)
7486 {
7487   if (sRef_isAllocated (s))
7488     {
7489       sRefSet_allElements (s->deriv, el)
7490         {
7491           if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
7492             {
7493               return FALSE;
7494             }
7495         } end_sRefSet_allElements ;
7496
7497       return TRUE;
7498     }
7499
7500   return FALSE;
7501 }
7502
7503 static bool
7504 sRef_isAllocatedStorage (sRef s)
7505 {
7506   if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isReadable (s)))
7507     {
7508       return (ctype_isVisiblySharable (sRef_getType (s)));
7509     }
7510   else
7511     {
7512       return FALSE;
7513     }
7514 }
7515
7516 bool
7517 sRef_isUnuseable (sRef s)
7518 {
7519   return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
7520 }
7521
7522 bool
7523 sRef_perhapsNull (sRef s)
7524 {
7525   if (sRef_isValid (s))
7526     {
7527       if (s->nullstate == NS_ABSNULL)
7528         {
7529           ctype rct = ctype_realType (s->type);
7530
7531           if (ctype_isAbstract (rct))
7532             {
7533               return FALSE;
7534             }
7535           else
7536             {
7537               if (ctype_isUser (rct))
7538                 {
7539                   uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
7540
7541                   return (nstate_perhapsNull 
7542                           (sRef_getNullState (uentry_getSref (ue))));
7543                 }
7544               else
7545                 {
7546                   return FALSE;
7547                 }
7548             }
7549         }
7550       else
7551         {
7552           return nstate_perhapsNull (s->nullstate);
7553         }
7554     }
7555
7556   return FALSE;
7557 }
7558
7559 /*
7560 ** definitelyNull --- called when TRUE is good
7561 */
7562
7563 bool 
7564 sRef_definitelyNull (sRef s)
7565 {
7566   return (sRef_isValid (s)
7567           && (s->nullstate == NS_DEFNULL || s->nullstate == NS_CONSTNULL));
7568 }
7569
7570 /*
7571 ** based on sRef_similar
7572 */
7573
7574 void
7575 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
7576 {
7577   if (sRef_isValid (set))
7578     {
7579       sRef deriv = sRef_getDeriv (set, guide);
7580       
7581       if (sRef_isValid (deriv))
7582         {
7583           deriv->nullstate = ns;
7584         }
7585     }
7586 }
7587
7588 static /*@exposed@*/ sRef
7589 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
7590 {
7591   llassert (sRef_isValid (set));
7592   llassert (sRef_isValid (guide));
7593
7594   switch (guide->kind)
7595     {
7596     case SK_CVAR:
7597       llassert (set->kind == SK_CVAR);
7598       
7599       return set;
7600
7601     case SK_PARAM:
7602       llassert (set->kind == guide->kind);
7603       llassert (set->info->paramno == guide->info->paramno);
7604
7605       return set;
7606
7607     case SK_ARRAYFETCH:
7608
7609       if (set->kind == SK_ARRAYFETCH
7610           && (sRef_similar (set->info->arrayfetch->arr,
7611                             guide->info->arrayfetch->arr)))
7612         {
7613           return set;
7614         }
7615       else
7616         {
7617           return (sRef_makeAnyArrayFetch 
7618                   (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
7619         }
7620
7621     case SK_PTR:
7622       
7623       if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
7624         {
7625           return set;
7626         }
7627       else
7628         {
7629           return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
7630         }
7631       
7632     case SK_FIELD:
7633       
7634       if ((set->kind == SK_FIELD &&
7635            (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
7636             cstring_equal (set->info->field->field, guide->info->field->field))))
7637         {
7638           return set;
7639         }
7640       else
7641         {
7642           return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
7643                                   guide->info->field->field));
7644         }
7645     case SK_ADR:
7646       
7647       if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
7648         {
7649           return set;
7650         }
7651       else
7652         {
7653           return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
7654         }
7655
7656     case SK_CONJ:
7657       
7658             return sRef_undefined;
7659
7660     case SK_RESULT:
7661     case SK_SPECIAL:
7662     case SK_UNCONSTRAINED:
7663     case SK_TYPE:
7664     case SK_CONST:
7665     case SK_NEW:
7666     case SK_UNKNOWN:
7667     case SK_OBJECT:
7668     case SK_DERIVED:
7669     case SK_EXTERNAL:
7670       return sRef_undefined;
7671     }
7672
7673   BADEXIT;
7674 }
7675       
7676 /*
7677 ** sRef_aliasCheckPred
7678 **
7679 ** A confusing but spiffy function:
7680 **
7681 **    Calls predf (s, e, text, <alias>) on s and all of s's aliases
7682 **    (unless checkAliases (s) is FALSE).
7683 **
7684 **    For alias calls, calls as
7685 **          predf (alias, e, text, s)
7686 */
7687
7688 void
7689 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
7690                      /*@null@*/ bool (checkAliases) (sRef),
7691                      sRef s, exprNode e, exprNode err)
7692 {
7693   bool error = (*predf)(s, e, sRef_undefined, err);
7694   
7695   
7696   if (checkAliases != NULL && !(checkAliases (s)))
7697     {
7698       /* don't check aliases */
7699     }
7700   else
7701     {
7702       sRefSet aliases = usymtab_allAliases (s);
7703
7704       
7705       sRefSet_realElements (aliases, current)
7706         {
7707           if (sRef_isValid (current))
7708             {
7709               if (!sRef_similar (current, s)
7710                   || (error && sRef_sameName (current, s)))
7711                 {
7712                   (void) (*predf)(current, e, s, err);
7713                 }
7714               }
7715         } end_sRefSet_realElements;
7716
7717       sRefSet_free (aliases);
7718     }
7719 }
7720
7721 /*
7722 ** return TRUE iff predf (s) is true for s or any alias of s
7723 */
7724
7725 bool
7726 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
7727 {
7728     
7729   if ((*predf)(s))
7730     {
7731       return TRUE;
7732     }
7733   else
7734     {
7735       sRefSet aliases;
7736
7737       aliases = usymtab_allAliases (s);
7738       
7739       sRefSet_realElements (aliases, current)
7740         {
7741           if (sRef_isValid (current))
7742             {
7743               sRef cref = sRef_updateSref (current);
7744               
7745               /* Whoa! a very kludgey way to make sure the right sref is used
7746               ** where there is a conditional symbol table.  I am beginning
7747               ** to think that having a conditional symbol table wasn't such
7748               ** a great idea.  ;(
7749               */
7750               
7751                       
7752               if ((*predf)(cref))
7753                 {
7754                   sRefSet_free (aliases);
7755                   return TRUE;
7756                 }
7757             }
7758         } end_sRefSet_realElements;
7759
7760       sRefSet_free (aliases);
7761     }
7762   return FALSE;
7763 }
7764
7765 bool
7766 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
7767 {
7768   sRefSet aliases;
7769   bool result = FALSE;
7770   
7771   
7772   aliases = usymtab_allAliases (s);
7773   
7774   if ((*predf)(s)) result = TRUE;
7775
7776   
7777   sRefSet_realElements (aliases, current)
7778     {
7779       if (sRef_isValid (current))
7780         {
7781                   current = sRef_updateSref (current);
7782                   if ((*predf)(current)) result = TRUE;
7783         }
7784     } end_sRefSet_realElements;
7785   
7786   sRefSet_free (aliases);
7787   return result;
7788 }
7789
7790 static void
7791 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
7792 {
7793   sRefSet aliases;
7794   
7795   aliases = usymtab_allAliases (s);
7796
7797   (*predf)(s, loc);
7798
7799   sRefSet_realElements (aliases, current)
7800     {
7801       if (sRef_isValid (current))
7802         {
7803           current = sRef_updateSref (current);
7804                   ((*predf)(current, loc));
7805         }
7806     } end_sRefSet_realElements;
7807
7808   sRefSet_free (aliases);
7809 }
7810
7811 static void
7812 sRef_aliasSetCompleteParam (void (predf) (sRef, alkind, fileloc), sRef s, 
7813                             alkind kind, fileloc loc)
7814 {
7815   sRefSet aliases;
7816
7817   
7818   if (sRef_isDeep (s))
7819     {
7820       aliases = usymtab_allAliases (s);
7821     }
7822   else
7823     {
7824       aliases = usymtab_aliasedBy (s);
7825     }
7826
7827   (*predf)(s, kind, loc);
7828
7829   sRefSet_realElements (aliases, current)
7830     {
7831       if (sRef_isValid (current))
7832         {
7833           current = sRef_updateSref (current);
7834                   ((*predf)(current, kind, loc));
7835         }
7836     } end_sRefSet_realElements;
7837
7838   sRefSet_free (aliases);
7839 }
7840
7841 static void
7842 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
7843 {
7844   sRef inner;
7845   sRefSet aliases;
7846   ctype ct;
7847
7848   if (!sRef_isValid (s)) return;
7849
7850   
7851   /*
7852   ** Type equivalence checking is necessary --- there might be casting.
7853   */
7854
7855   (*predf)(s, loc);
7856
7857   switch (s->kind)
7858     {
7859     case SK_UNCONSTRAINED:
7860     case SK_CVAR:
7861     case SK_PARAM:
7862       break;
7863     case SK_PTR:
7864       inner = s->info->ref;
7865       aliases = usymtab_allAliases (inner);
7866       ct = sRef_getType (inner);
7867
7868       
7869       sRefSet_realElements (aliases, current)
7870         {
7871           if (sRef_isValid (current))
7872             {
7873               current = sRef_updateSref (current);
7874               
7875               if (ctype_equal (ct, sRef_getType (current)))
7876                 {
7877                   sRef ptr = sRef_makePointer (current);
7878                   
7879                   ((*predf)(ptr, loc));
7880                 }
7881             }
7882         } end_sRefSet_realElements;
7883
7884       sRefSet_free (aliases);
7885       break;
7886     case SK_ARRAYFETCH:
7887       inner = s->info->arrayfetch->arr;
7888       aliases = usymtab_allAliases (inner);
7889       ct = sRef_getType (inner);
7890
7891       sRefSet_realElements (aliases, current)
7892         {
7893           if (sRef_isValid (current))
7894             {
7895               current = sRef_updateSref (current);
7896               
7897               if (ctype_equal (ct, sRef_getType (current)))
7898                 {
7899                                   
7900                   if (s->info->arrayfetch->indknown)
7901                     {
7902                       sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
7903                       
7904                       ((*predf)(af, loc));
7905                     }
7906                   else
7907                     {
7908                       sRef af = sRef_makeArrayFetch (current);
7909                       
7910                       ((*predf)(af, loc));
7911                     }
7912                 }
7913             }
7914         } end_sRefSet_realElements;
7915
7916       sRefSet_free (aliases);
7917       break;
7918     case SK_FIELD:
7919       inner = s->info->field->rec;
7920       aliases = usymtab_allAliases (inner);
7921       ct = sRef_getType (inner);
7922
7923       
7924       sRefSet_realElements (aliases, current)
7925         {
7926           if (sRef_isValid (current))
7927             {
7928               current = sRef_updateSref (current);
7929               
7930               if (ctype_equal (ct, sRef_getType (current)))
7931                 {
7932                   sRef f = sRef_makeField (current, s->info->field->field);
7933                   
7934                   ((*predf)(f, loc));
7935                 }
7936             }
7937         } end_sRefSet_realElements;
7938       
7939       sRefSet_free (aliases);
7940       break;
7941     case SK_CONJ:
7942       sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
7943       sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
7944       break;
7945     case SK_SPECIAL:
7946     case SK_ADR:
7947     case SK_TYPE:
7948     case SK_CONST:
7949     case SK_NEW:
7950     case SK_UNKNOWN:
7951     case SK_OBJECT:
7952     case SK_DERIVED:
7953     case SK_EXTERNAL:
7954     case SK_RESULT:
7955       break;
7956     }
7957 }
7958
7959 static void
7960 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
7961 {
7962   sRef inner;
7963   sRefSet aliases;
7964   ctype ct;
7965
7966   if (!sRef_isValid (s)) return;
7967
7968   
7969   /*
7970   ** Type equivalence checking is necessary --- there might be casting.
7971   */
7972
7973   (*predf)(s, t);
7974
7975   switch (s->kind)
7976     {
7977     case SK_UNCONSTRAINED:
7978     case SK_CVAR:
7979     case SK_PARAM:
7980       break;
7981     case SK_PTR:
7982       inner = s->info->ref;
7983       aliases = usymtab_allAliases (inner);
7984       ct = sRef_getType (inner);
7985       
7986       
7987       sRefSet_realElements (aliases, current)
7988         {
7989           if (sRef_isValid (current))
7990             {
7991               current = sRef_updateSref (current);
7992               
7993               if (ctype_equal (ct, sRef_getType (current)))
7994                 {
7995                   sRef ptr = sRef_makePointer (current);
7996                   
7997                   ((*predf)(ptr, t));
7998                 }
7999             }
8000         } end_sRefSet_realElements;
8001
8002       sRefSet_free (aliases);
8003       break;
8004     case SK_ARRAYFETCH:
8005       inner = s->info->arrayfetch->arr;
8006       aliases = usymtab_allAliases (inner);
8007       ct = sRef_getType (inner);
8008
8009       sRefSet_realElements (aliases, current)
8010         {
8011           if (sRef_isValid (current))
8012             {
8013               current = sRef_updateSref (current);
8014               
8015               if (ctype_equal (ct, sRef_getType (current)))
8016                 {
8017                                   
8018                   if (s->info->arrayfetch->indknown)
8019                     {
8020                       sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
8021                       
8022                       ((*predf)(af, t));
8023                     }
8024                   else
8025                     {
8026                       sRef af = sRef_makeArrayFetch (current);
8027                       
8028                       ((*predf)(af, t));
8029                     }
8030                 }
8031             }
8032         } end_sRefSet_realElements;
8033
8034       sRefSet_free (aliases);
8035       break;
8036     case SK_FIELD:
8037       inner = s->info->field->rec;
8038       aliases = usymtab_allAliases (inner);
8039       ct = sRef_getType (inner);
8040
8041       
8042       sRefSet_realElements (aliases, current)
8043         {
8044           if (sRef_isValid (current))
8045             {
8046               current = sRef_updateSref (current);
8047               
8048               if (ctype_equal (ct, sRef_getType (current)))
8049                 {
8050                   sRef f = sRef_makeField (current, s->info->field->field);
8051                   
8052                   ((*predf)(f, t));
8053                 }
8054             }
8055         } end_sRefSet_realElements;
8056       
8057       sRefSet_free (aliases);
8058       break;
8059     case SK_CONJ:
8060       sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
8061       sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
8062       break;
8063     case SK_SPECIAL:
8064     case SK_ADR:
8065     case SK_TYPE:
8066     case SK_CONST:
8067     case SK_NEW:
8068     case SK_UNKNOWN:
8069     case SK_OBJECT:
8070     case SK_DERIVED:
8071     case SK_EXTERNAL:
8072     case SK_RESULT:
8073       break;
8074     }
8075 }
8076
8077 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8078 {
8079   exkind a1 = sRef_getExKind (res);
8080   exkind a2 = sRef_getExKind (other);
8081
8082   if (a1 == a2 || a2 == XO_UNKNOWN) 
8083     {
8084       ;
8085     }
8086   else if (a1 == XO_UNKNOWN) 
8087     { 
8088       res->expinfo = alinfo_update (res->expinfo, other->expinfo);
8089       res->expkind = a2;
8090     }
8091   else
8092     {
8093       res->expkind = XO_OBSERVER;
8094     }
8095 }
8096
8097 /*
8098 ** Currently, this is a very ad hoc implementation, with lots of fixes to
8099 ** make real code work okay.  I need to come up with some more general
8100 ** rules or principles here.
8101 */
8102
8103 static void 
8104   sRef_combineAliasKindsError (/*@notnull@*/ sRef res, 
8105                                /*@notnull@*/ sRef other, 
8106                                clause cl, fileloc loc)
8107 {
8108   bool hasError = FALSE;
8109   alkind ares = sRef_getAliasKind (res);
8110   alkind aother = sRef_getAliasKind (other);
8111
8112   if (alkind_isDependent (ares))
8113     {
8114       if (aother == AK_KEPT)
8115         {
8116           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8117           res->aliaskind = AK_KEPT;      
8118         }
8119       else 
8120         {
8121           if (aother == AK_LOCAL || aother == AK_STATIC 
8122               || alkind_isTemp (aother))
8123             {
8124               res->aliaskind = AK_DEPENDENT;
8125             }
8126         }
8127     }
8128   else if (alkind_isDependent (aother))
8129     {
8130       if (ares == AK_KEPT)
8131         {
8132           res->aliaskind = AK_KEPT;      
8133         }
8134       else 
8135         {
8136           if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
8137             {
8138               res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8139               res->aliaskind = AK_DEPENDENT;
8140             }
8141         }
8142     }
8143   else if ((ares == AK_LOCAL || ares == AK_UNIQUE
8144             || ares == AK_STATIC || alkind_isTemp (ares))
8145            && sRef_isFresh (other))
8146     {
8147       /*
8148       ** cases like: if (s == NULL) s = malloc...;
8149       **    don't generate errors
8150       */
8151       
8152       if (usymtab_isAltProbablyDeepNull (res))
8153         {
8154           res->aliaskind = ares;
8155         }
8156       else
8157         {
8158           hasError = TRUE; 
8159         }
8160     }
8161   else if ((aother == AK_LOCAL || aother == AK_UNIQUE
8162             || aother == AK_STATIC || alkind_isTemp (aother))
8163            && sRef_isFresh (res))
8164     {
8165       /*
8166       ** cases like: if (s == NULL) s = malloc...;
8167       **    don't generate errors
8168       */
8169       
8170       if (usymtab_isProbableDeepNull (other))
8171         {
8172           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8173           res->aliaskind = aother;
8174         }
8175       else
8176         {
8177           hasError = TRUE;
8178         }
8179     }
8180   else if (ares == AK_NEWREF && aother == AK_REFCOUNTED 
8181            && sRef_isConst (other))
8182     {
8183       res->aliaskind = AK_NEWREF;
8184     }
8185   else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
8186            && sRef_isConst (res))
8187     {
8188       res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8189       res->aliaskind = AK_NEWREF;
8190     }
8191   else if (sRef_isLocalVar (res)
8192            && ((ares == AK_KEPT && aother == AK_LOCAL)
8193                || (aother == AK_KEPT && ares == AK_LOCAL)))
8194     {
8195       res->aliaskind = AK_KEPT;
8196     }
8197   else
8198     {
8199       hasError = TRUE;
8200     }
8201
8202   if (hasError)
8203     {
8204       if (sRef_isThroughArrayFetch (res))
8205         {
8206           if (optgenerror2 
8207               (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
8208                message
8209                ("Clauses exit with %q possibly referencing %s storage %s, "
8210                 "%s storage %s", 
8211                 sRef_unparse (res),
8212                 alkind_unparse (aother),
8213                 clause_nameTaken (cl),
8214                 alkind_unparse (ares),
8215                 clause_nameAlternate (cl)),
8216                loc))
8217             {
8218               sRef_showAliasInfo (res);
8219               sRef_showAliasInfo (other);
8220               res->aliaskind = AK_ERROR;
8221             }
8222           else
8223             {
8224               if (ares == AK_KEPT || aother == AK_KEPT)
8225                 {
8226                   sRef_maybeKill (res, loc);
8227                                 }
8228             }
8229         }
8230       else 
8231         {
8232           if (optgenerror 
8233               (FLG_BRANCHSTATE,
8234                message ("Clauses exit with %q referencing %s storage %s, "
8235                         "%s storage %s", 
8236                         sRef_unparse (res),
8237                         alkind_unparse (aother),
8238                         clause_nameTaken (cl),
8239                         alkind_unparse (ares),
8240                         clause_nameAlternate (cl)),
8241                loc))
8242             {
8243               sRef_showAliasInfo (res);
8244               sRef_showAliasInfo (other);
8245               
8246               res->aliaskind = AK_ERROR;
8247             }
8248         }
8249       
8250       res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
8251     }
8252 }
8253
8254 static void 
8255   sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other, 
8256                           clause cl, fileloc loc)
8257 {
8258   alkind ares = sRef_getAliasKind (res);
8259   alkind aother = sRef_getAliasKind (other);
8260
8261   if (alkind_equal (ares, aother)
8262       || aother == AK_UNKNOWN
8263       || aother == AK_ERROR)
8264     {
8265       ; /* keep current state */
8266     }
8267   else if (sRef_isDead (res) || sRef_isDead (other))
8268     {
8269       /* dead error reported (or storage is dead) */
8270       res ->aliaskind = AK_ERROR; 
8271     }
8272   else if (ares == AK_UNKNOWN || ares == AK_ERROR
8273            || sRef_isStateUndefined (res))
8274     { 
8275       res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8276       res->aliaskind = aother;  
8277     }
8278   else if (sRef_isStateUndefined (other))
8279     {
8280       ;
8281     }
8282   else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
8283             && aother == AK_LOCAL) 
8284            || ((aother == AK_UNIQUE || alkind_isTemp (aother))
8285                && ares == AK_LOCAL))
8286     {
8287       if (ares != AK_LOCAL)
8288         {
8289           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8290         }
8291
8292       res->aliaskind = AK_LOCAL;
8293     }
8294   else if ((ares == AK_OWNED && aother == AK_FRESH) 
8295            || (aother == AK_OWNED && ares == AK_FRESH))
8296     {
8297       if (ares != AK_FRESH)
8298         {
8299           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8300         }
8301       
8302       res->aliaskind = AK_FRESH;
8303     }
8304   else if ((ares == AK_KEEP && aother == AK_FRESH) ||
8305            (aother == AK_KEEP && ares == AK_FRESH))
8306     {
8307       if (ares != AK_KEEP)
8308         {
8309           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8310         }
8311       
8312       res->aliaskind = AK_KEEP;
8313     }
8314   else if ((ares == AK_LOCAL && aother == AK_STACK) ||
8315            (aother == AK_LOCAL && ares == AK_STACK))
8316     {
8317       if (ares != AK_STACK)
8318         {
8319           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8320         }
8321
8322       res->aliaskind = AK_STACK;
8323     }
8324   else if ((ares == AK_LOCAL
8325             && (aother == AK_OWNED && sRef_isLocalVar (other)))
8326            || (aother == AK_LOCAL 
8327                && (ares == AK_OWNED && sRef_isLocalVar (res))))
8328     {
8329       if (ares != AK_LOCAL)
8330         {
8331           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8332         }
8333
8334       res->aliaskind = AK_LOCAL;
8335     }
8336   else if ((ares == AK_FRESH && alkind_isOnly (aother))
8337            || (aother == AK_FRESH && alkind_isOnly (ares)))
8338     {
8339       res->aliaskind = AK_FRESH;
8340     }
8341   else if ((aother == AK_FRESH && sRef_definitelyNull (res))
8342            || (ares == AK_FRESH && sRef_definitelyNull (other)))
8343     {
8344       if (ares != AK_FRESH)
8345         {
8346           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8347           res->aliaskind = AK_FRESH;
8348         }
8349     }
8350   else if ((sRef_isFresh (res) && sRef_isConst (other))
8351            || (sRef_isFresh (other) && sRef_isConst (res)))
8352     {
8353       /*
8354       ** for NULL constantants
8355       ** this is bogus!
8356       */
8357
8358       if (!sRef_isFresh (res))
8359         {
8360           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8361         }
8362
8363       res->aliaskind = AK_FRESH;
8364     }
8365   else if ((alkind_isStatic (aother) && sRef_isConst (res))
8366            || (alkind_isStatic (ares) && sRef_isConst (other)))
8367     {
8368       if (!alkind_isStatic (ares))
8369         {
8370           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
8371           res->aliaskind = AK_STATIC;
8372         }
8373     }
8374   else
8375     {
8376       sRef_combineAliasKindsError (res, other, cl, loc);
8377     }
8378 }
8379
8380 static void sRef_combineDefState (/*@notnull@*/ sRef res, 
8381                                   /*@notnull@*/ sRef other)
8382 {
8383   sstate s1 = res->defstate;
8384   sstate s2 = other->defstate;
8385   bool flip = FALSE;
8386
8387   if (s1 == s2 || s2 == SS_UNKNOWN)
8388     {
8389       ;
8390     }
8391   else if (s1 == SS_UNKNOWN)
8392     {
8393       flip = TRUE;
8394     }
8395   else
8396     {
8397       switch (s1)
8398         {
8399         case SS_FIXED:   
8400           if (s2 == SS_DEFINED) 
8401             {
8402               break;
8403             }
8404           else
8405             {
8406               llcontbuglit ("ssfixed: not implemented");
8407               flip = TRUE;
8408             }
8409           break;
8410         case SS_DEFINED: 
8411           flip = TRUE;
8412           break;
8413         case SS_PDEFINED:
8414         case SS_ALLOCATED: 
8415           flip = (s2 != SS_DEFINED);
8416           break;
8417         case SS_HOFFA:
8418         case SS_RELDEF:
8419         case SS_UNUSEABLE: 
8420         case SS_UNDEFINED: 
8421         case SS_PARTIAL:
8422         case SS_UNDEFGLOB:
8423         case SS_KILLED:
8424         case SS_DEAD:      
8425         case SS_SPECIAL: 
8426           break;
8427         BADDEFAULT;
8428         }
8429     }
8430
8431   if (flip)
8432     {
8433       res->definfo = alinfo_update (res->definfo, other->definfo);
8434       res->defstate = s2;
8435     }
8436 }
8437
8438 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
8439 {
8440   sRef ret;
8441   llassert (sRef_isConj (s));
8442
8443   ret = s->info->conj->a;
8444   llassert (ret != NULL);
8445   return ret;
8446 }
8447
8448 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
8449 {
8450   sRef ret;
8451   llassert (sRef_isConj (s));
8452
8453   ret = s->info->conj->b;
8454   llassert (ret != NULL);
8455   return ret;
8456 }
8457   
8458 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
8459 {
8460   sRef p;
8461   sRef ret;
8462
8463     p = sRef_makePointer (s);
8464   ret = sRef_makeField (p, f);
8465     return ret;
8466 }
8467
8468 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
8469 {
8470   sRef p;
8471   sRef ret;
8472
8473   p = sRef_buildPointer (s);
8474   ret = sRef_buildField (p, f);
8475   
8476   return ret;
8477 }
8478
8479 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
8480 {
8481   sinfo ret;
8482
8483   switch (s->kind)
8484     {
8485     case SK_CVAR:
8486       ret = (sinfo) dmalloc (sizeof (*ret));
8487       ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8488       ret->cvar->lexlevel = s->info->cvar->lexlevel; 
8489       ret->cvar->index = s->info->cvar->index; 
8490       break;
8491
8492     case SK_PARAM:
8493       ret = (sinfo) dmalloc (sizeof (*ret));
8494       ret->paramno = s->info->paramno; 
8495       break;
8496
8497     case SK_ARRAYFETCH:
8498       ret = (sinfo) dmalloc (sizeof (*ret));
8499       ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8500       ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8501       ret->arrayfetch->ind = s->info->arrayfetch->ind;
8502       ret->arrayfetch->arr = s->info->arrayfetch->arr;
8503       break;
8504
8505     case SK_FIELD:
8506       ret = (sinfo) dmalloc (sizeof (*ret));
8507       ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8508       ret->field->rec = s->info->field->rec;
8509       ret->field->field = s->info->field->field; 
8510       break;
8511
8512     case SK_OBJECT:
8513       ret = (sinfo) dmalloc (sizeof (*ret));
8514       ret->object = s->info->object;
8515       break;
8516
8517     case SK_PTR:
8518     case SK_ADR:
8519     case SK_DERIVED:
8520     case SK_EXTERNAL:
8521       ret = (sinfo) dmalloc (sizeof (*ret));
8522       ret->ref = s->info->ref;   
8523       break;
8524
8525     case SK_CONJ:
8526       ret = (sinfo) dmalloc (sizeof (*ret));
8527       ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
8528       ret->conj->a = s->info->conj->a;
8529       ret->conj->b = s->info->conj->b;
8530       break;
8531     case SK_SPECIAL:
8532       ret = (sinfo) dmalloc (sizeof (*ret));
8533       ret->spec = s->info->spec;
8534       break;
8535     case SK_UNCONSTRAINED:
8536     case SK_NEW:
8537       ret = (sinfo) dmalloc (sizeof (*ret));
8538       ret->fname = s->info->fname;
8539       break;
8540     case SK_RESULT:
8541     case SK_CONST:
8542     case SK_TYPE:
8543     case SK_UNKNOWN:
8544       llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
8545       ret = NULL;
8546       break;
8547     }
8548
8549   return ret;
8550 }
8551
8552 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
8553 {
8554   sinfo ret;
8555
8556   /*
8557   ** Since its a full copy, only storage is assigned
8558   ** to dependent fields.
8559   */
8560   /*@-onlytrans@*/
8561
8562   switch (s->kind)
8563     {
8564     case SK_CVAR:
8565       ret = (sinfo) dmalloc (sizeof (*ret));
8566       ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
8567       ret->cvar->lexlevel = s->info->cvar->lexlevel; 
8568       ret->cvar->index = s->info->cvar->index; 
8569       break;
8570
8571     case SK_PARAM:
8572       ret = (sinfo) dmalloc (sizeof (*ret));
8573       ret->paramno = s->info->paramno; 
8574       break;
8575
8576     case SK_ARRAYFETCH:
8577       ret = (sinfo) dmalloc (sizeof (*ret));
8578       ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
8579       ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
8580       ret->arrayfetch->ind = s->info->arrayfetch->ind;
8581       ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
8582       break;
8583
8584     case SK_FIELD:
8585       ret = (sinfo) dmalloc (sizeof (*ret));
8586       ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
8587       ret->field->rec = sRef_saveCopy (s->info->field->rec);
8588       ret->field->field = s->info->field->field; 
8589       break;
8590
8591     case SK_OBJECT:
8592       ret = (sinfo) dmalloc (sizeof (*ret));
8593       ret->object = s->info->object;
8594       break;
8595
8596     case SK_PTR:
8597     case SK_ADR:
8598     case SK_DERIVED:
8599     case SK_EXTERNAL:
8600       ret = (sinfo) dmalloc (sizeof (*ret));
8601       ret->ref = sRef_saveCopy (s->info->ref);   
8602       break;
8603
8604     case SK_CONJ:
8605       ret = (sinfo) dmalloc (sizeof (*ret));
8606       ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
8607       ret->conj->a = sRef_saveCopy (s->info->conj->a);
8608       ret->conj->b = sRef_saveCopy (s->info->conj->b);
8609       break;
8610     case SK_SPECIAL:
8611       ret = (sinfo) dmalloc (sizeof (*ret));
8612       ret->spec = s->info->spec;
8613       break;
8614     case SK_NEW:
8615     case SK_UNCONSTRAINED:
8616       ret = (sinfo) dmalloc (sizeof (*ret));
8617       ret->fname = s->info->fname;
8618       break;
8619     case SK_CONST:
8620     case SK_TYPE:
8621     case SK_RESULT:
8622     case SK_UNKNOWN:
8623       llassert (s->info == NULL);
8624       ret = NULL;
8625       break;
8626     }
8627   /*@=onlytrans@*/ 
8628   return ret;
8629 }
8630
8631
8632 static void 
8633   sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res, 
8634                 /*@notnull@*/ /*@exposed@*/ sRef other)
8635 {
8636   llassert (res->kind == other->kind);
8637
8638   switch (res->kind)
8639     {
8640     case SK_CVAR:
8641       res->info->cvar->lexlevel = other->info->cvar->lexlevel; 
8642       res->info->cvar->index = other->info->cvar->index; 
8643       break;
8644
8645     case SK_PARAM:
8646       res->info->paramno = other->info->paramno; 
8647       break;
8648
8649     case SK_ARRAYFETCH:
8650       res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
8651       res->info->arrayfetch->ind = other->info->arrayfetch->ind;
8652       res->info->arrayfetch->arr = other->info->arrayfetch->arr;
8653       break;
8654
8655     case SK_FIELD:
8656       res->info->field->rec = other->info->field->rec;
8657       res->info->field->field = other->info->field->field; 
8658       break;
8659
8660     case SK_OBJECT:
8661       res->info->object = other->info->object;
8662       break;
8663
8664     case SK_PTR:
8665     case SK_ADR:
8666     case SK_DERIVED:
8667     case SK_EXTERNAL:
8668       res->info->ref = other->info->ref;         
8669       break;
8670
8671     case SK_CONJ:
8672       res->info->conj->a = other->info->conj->a;
8673       res->info->conj->b = other->info->conj->b;
8674       break;
8675
8676     case SK_SPECIAL:
8677       res->info->spec = other->info->spec;
8678       break;
8679
8680     case SK_NEW:
8681     case SK_UNCONSTRAINED:
8682       res->info->fname = other->info->fname;
8683       break;
8684
8685     case SK_CONST:
8686     case SK_TYPE:
8687     case SK_UNKNOWN:
8688     case SK_RESULT:
8689       llassert (res->info == NULL);
8690       break;
8691     }
8692 }
8693
8694 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
8695    /*@uses s->kind, s->info@*/
8696    /*@releases s->info@*/ 
8697 {
8698   switch (s->kind)
8699     {
8700     case SK_CVAR:
8701       sfree (s->info->cvar);
8702       break;
8703
8704     case SK_PARAM:
8705       break;
8706
8707     case SK_ARRAYFETCH:
8708       sfree (s->info->arrayfetch);
8709       break;
8710
8711     case SK_FIELD:
8712       sfree (s->info->field); 
8713       break;
8714
8715     case SK_OBJECT:
8716       break;
8717
8718     case SK_PTR:
8719     case SK_ADR:
8720     case SK_DERIVED:
8721     case SK_EXTERNAL:
8722       break;
8723
8724     case SK_CONJ:
8725       sfree (s->info->conj);
8726       break;
8727
8728     case SK_UNCONSTRAINED:
8729     case SK_SPECIAL:
8730     case SK_CONST:
8731     case SK_NEW:
8732     case SK_TYPE:
8733     case SK_UNKNOWN:
8734     case SK_RESULT:
8735       break;
8736     }
8737
8738   sfree (s->info);
8739 }
8740
8741 bool sRef_isNSLocalVar (sRef s)  
8742 {
8743   if (sRef_isLocalVar (s))
8744     {
8745       uentry ue = sRef_getUentry (s);
8746
8747       return (!uentry_isStatic (ue));
8748     }
8749   else
8750     {
8751       return FALSE;
8752     }
8753 }
8754
8755 bool sRef_isLocalVar (sRef s)  
8756 {
8757   if (sRef_isValid(s))
8758     {
8759       return (s->kind == SK_CVAR 
8760               && (s->info->cvar->lexlevel > fileScope));
8761     }
8762   
8763   return FALSE;
8764 }
8765
8766 bool sRef_isRealLocalVar (sRef s)  
8767 {
8768   if (sRef_isValid(s))
8769     {
8770       if (s->kind == SK_CVAR)
8771         {
8772           if (s->info->cvar->lexlevel == functionScope)
8773             {
8774               uentry ue = sRef_getUentry (s);
8775
8776               if (uentry_isAnyParam (ue)
8777                   || uentry_isRefParam (ue))
8778                 {
8779                   return FALSE;
8780                 }
8781               else
8782                 {
8783                   return TRUE;
8784                 }
8785             }
8786           else
8787             {
8788               return (s->info->cvar->lexlevel > functionScope);
8789             }
8790         }
8791     }
8792   
8793   return FALSE;
8794 }
8795
8796 bool sRef_isLocalParamVar (sRef s)  
8797 {
8798   if (sRef_isValid(s))
8799     {
8800       return (s->kind == SK_PARAM
8801               || (s->kind == SK_CVAR 
8802                   && (s->info->cvar->lexlevel > fileScope)));
8803     }
8804   
8805   return FALSE;
8806 }
8807
8808 static speckind speckind_fromInt (int i)
8809 {
8810   /*@+enumint@*/ 
8811   llassert (i >= SR_NOTHING && i <= SR_SYSTEM); 
8812   /*@=enumint@*/
8813
8814   return ((speckind) i);
8815 }
8816
8817 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
8818 {
8819   nstate n1 = res->nullstate;
8820   nstate n2 = other->nullstate;
8821   bool flip = FALSE;
8822   nstate nn = n1;
8823
8824   if (n1 == n2 || n2 == NS_UNKNOWN)
8825     {
8826       ;
8827     }
8828   else
8829     {
8830       /* note: n2 is not unknown or defnull */
8831
8832       switch (n1)
8833         {
8834         case NS_ERROR:   nn = NS_ERROR; break;
8835         case NS_UNKNOWN: flip = TRUE; nn = n2; break; 
8836         case NS_POSNULL: break;
8837         case NS_DEFNULL: nn = NS_POSNULL; break;
8838         case NS_RELNULL: break;
8839         case NS_NOTNULL:  
8840           if (n2 == NS_MNOTNULL)
8841             {
8842               ;
8843             }
8844           else 
8845             { 
8846               flip = TRUE;
8847               nn = NS_POSNULL; 
8848             }
8849           break;
8850         case NS_MNOTNULL: 
8851           if (n2 == NS_NOTNULL) 
8852             {
8853               nn = NS_NOTNULL; 
8854             }
8855           else 
8856             {
8857               flip = TRUE;
8858               nn = NS_POSNULL; 
8859             }
8860           break;
8861         case NS_CONSTNULL:
8862         case NS_ABSNULL:
8863           flip = TRUE;
8864           nn = n2;
8865         }
8866     }
8867   
8868   if (flip)
8869     {
8870       res->nullinfo = alinfo_update (res->nullinfo, other->nullinfo);      
8871     }
8872
8873   res->nullstate = nn;
8874 }
8875
8876 cstring sRef_nullMessage (sRef s)
8877 {
8878   llassert (sRef_isValid (s));
8879
8880   switch (s->nullstate)
8881     {
8882     case NS_DEFNULL:
8883     case NS_CONSTNULL:
8884       return (cstring_makeLiteralTemp ("null"));
8885     default:
8886       return (cstring_makeLiteralTemp ("possibly null"));
8887     }
8888   BADEXIT;
8889 }
8890
8891 /*@observer@*/ cstring sRef_ntMessage (sRef s)
8892 {
8893   llassert (sRef_isValid (s));
8894
8895   switch (s->nullstate)
8896     {
8897     case NS_DEFNULL:
8898     case NS_CONSTNULL:
8899       return (cstring_makeLiteralTemp ("not nullterminated"));
8900     default:
8901       return (cstring_makeLiteralTemp ("possibly non-nullterminated"));
8902     }
8903   BADEXIT;
8904 }
8905
8906
8907
8908 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
8909 {
8910   sRef tmp = sRef_undefined;
8911   sRef ret;
8912
8913   llassert (sRef_isValid (s));
8914
8915   switch (s->kind)
8916     {
8917     case SK_RESULT:
8918       s->type = typ;
8919       ret = s;
8920       break;
8921     case SK_ARRAYFETCH:
8922       {
8923         ctype ct;
8924         tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
8925
8926         ct = ctype_realType (sRef_getType (tmp));
8927
8928         
8929         if (ctype_isKnown (ct))
8930           {
8931             if (ctype_isAP (ct))
8932               {
8933                 ;
8934               }
8935             else
8936               {
8937                 voptgenerror 
8938                   (FLG_TYPE,
8939                    message
8940                    ("Special clause indexes non-array (%t): *%q",
8941                     ct, sRef_unparse (s->info->arrayfetch->arr)),
8942                    uentry_whereLast (ue));
8943               }
8944           }
8945
8946         tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
8947
8948         if (s->info->arrayfetch->indknown)
8949           {
8950             ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
8951           }
8952         else
8953           {
8954             ret = sRef_makeArrayFetch (tmp);
8955           }
8956       }
8957       break;
8958     case SK_FIELD:
8959       {
8960         sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
8961         ctype ct = ctype_realType (sRef_getType (rec));
8962
8963         if (ctype_isKnown (ct))
8964           {
8965             if (ctype_isSU (ct))
8966               {
8967                 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct), 
8968                                                             s->info->field->field)))
8969                   {
8970                     ;
8971                   }
8972                 else
8973                   {
8974                     voptgenerror 
8975                       (FLG_TYPE,
8976                        message
8977                        ("Special clause accesses non-existent field of result: %q.%s",
8978                         sRef_unparse (rec), s->info->field->field),
8979                        uentry_whereLast (ue));
8980                   }
8981               }
8982             else
8983               {
8984                 voptgenerror 
8985                   (FLG_TYPE,
8986                    message
8987                    ("Special clause accesses field of non-struct or union result (%t): %q.%s",
8988                     ct, sRef_unparse (rec), s->info->field->field),
8989                    uentry_whereLast (ue));
8990               }
8991           }
8992         
8993         ret = sRef_makeField (tmp, s->info->field->field);
8994         break;
8995       }
8996     case SK_PTR:
8997       {
8998         ctype ct;
8999         tmp = sRef_fixResultType (s->info->ref, typ, ue);
9000
9001         ct = ctype_realType (sRef_getType (tmp));
9002
9003         if (ctype_isKnown (ct))
9004           {
9005             if (ctype_isAP (ct))
9006               {
9007                 ;
9008               }
9009             else
9010               {
9011                 voptgenerror 
9012                   (FLG_TYPE,
9013                    message
9014                    ("Special clause dereferences non-pointer (%t): *%q",
9015                     ct, sRef_unparse (s->info->ref)),
9016                    uentry_whereLast (ue));
9017               }
9018           }
9019         
9020         ret = sRef_makePointer (tmp);
9021         break;
9022       }
9023     case SK_ADR:
9024       voptgenerror 
9025         (FLG_TYPE,
9026          message
9027          ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
9028          uentry_whereLast (ue));
9029       ret = s;
9030       break;
9031     BADDEFAULT;
9032     }
9033
9034   return ret;
9035 }
9036
9037 bool sRef_isOnly (sRef s)
9038 {
9039   return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
9040 }
9041
9042 bool sRef_isDependent (sRef s) 
9043 {
9044   return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
9045 }
9046
9047 bool sRef_isOwned (sRef s)
9048 {
9049   return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
9050 }
9051
9052 bool sRef_isKeep (sRef s) 
9053 {
9054   return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
9055 }
9056
9057 bool sRef_isTemp (sRef s)
9058 {
9059   return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
9060 }
9061
9062 bool sRef_isLocalState (sRef s) 
9063 {
9064   return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
9065 }
9066
9067 bool sRef_isUnique (sRef s)
9068 {
9069   return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
9070 }
9071
9072 bool sRef_isShared (sRef s) 
9073 {
9074   return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
9075 }
9076
9077 bool sRef_isExposed (sRef s) 
9078 {
9079   return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
9080 }
9081
9082 bool sRef_isObserver (sRef s) 
9083 {
9084   return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
9085 }
9086
9087 bool sRef_isFresh (sRef s) 
9088 {
9089   return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
9090 }
9091
9092 bool sRef_isDefinitelyNull (sRef s) 
9093 {
9094   return (sRef_isValid (s) && (s->nullstate == NS_DEFNULL 
9095                                || s->nullstate == NS_CONSTNULL));
9096 }
9097
9098 bool sRef_isAllocated (sRef s)
9099 {
9100   return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
9101 }
9102
9103 bool sRef_isStack (sRef s)
9104 {
9105   return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
9106 }
9107
9108 extern bool sRef_isNotNull (sRef s)
9109 {
9110   return (sRef_isValid(s) && (s->nullstate == NS_MNOTNULL 
9111                               || s->nullstate == NS_NOTNULL));
9112 }
9113
9114 /* start modifications */
9115 struct _bbufinfo sRef_getNullTerminatedState (sRef p_s) {
9116    struct _bbufinfo BUFSTATE_UNKNOWN;
9117    BUFSTATE_UNKNOWN.bufstate = BB_NOTNULLTERMINATED;
9118    BUFSTATE_UNKNOWN.size = 0;
9119    BUFSTATE_UNKNOWN.len = 0;
9120    
9121    if (sRef_isValid(p_s))
9122       return p_s->bufinfo;
9123    return BUFSTATE_UNKNOWN; 
9124 }
9125
9126 void sRef_setNullTerminatedState(sRef p_s) {
9127    if(sRef_isValid (p_s)) {
9128       p_s->bufinfo.bufstate = BB_NULLTERMINATED;
9129    } else {
9130       llfatalbug( message("sRef_setNT passed a invalid sRef\n"));
9131    }
9132 }
9133
9134
9135 void sRef_setPossiblyNullTerminatedState(sRef p_s) {
9136    if( sRef_isValid (p_s)) {
9137       p_s->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
9138    } else {
9139       llfatalbug( message("sRef_setPossNT passed a invalid sRef\n"));
9140    }
9141 }
9142
9143 void sRef_setNotNullTerminatedState(sRef p_s) {
9144    if( sRef_isValid (p_s)) {
9145       p_s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
9146    } else {
9147       llfatalbug( message("sRef_unsetNT passed a invalid sRef\n"));
9148    }
9149 }
9150
9151 void sRef_setLen(sRef p_s, int len) {
9152    if( sRef_isValid (p_s) && sRef_isNullTerminated(p_s)) {
9153       p_s->bufinfo.len = len;
9154    } else {
9155       llfatalbug( message("sRef_setLen passed a invalid sRef\n"));
9156    }
9157 }
9158     
9159
9160 void sRef_setSize(sRef p_s, int size) {
9161    if( sRef_isValid(p_s)) {
9162        p_s->bufinfo.size = size;
9163    } else {
9164       llfatalbug( message("sRef_setSize passed a invalid sRef\n"));
9165    }
9166 }
9167
9168 void sRef_resetLen(sRef p_s) {
9169         if (sRef_isValid (p_s)) {
9170                 p_s->bufinfo.len = 0;
9171         } else {
9172                 llfatalbug (message ("sRef_setLen passed an invalid sRef\n"));
9173         }
9174 }
9175
9176 /*drl7x 11/28/2000 */
9177
9178 bool sRef_isFixedArray (sRef p_s) /*@*/ {
9179   ctype c;
9180   c = sRef_getType (p_s);
9181   return ( ctype_isFixedArray (c) );
9182 }
9183
9184 long int sRef_getArraySize (sRef p_s) /*@*/ {
9185   ctype c;
9186   llassert (sRef_isFixedArray(p_s) );
9187   DPRINTF (( message ("sRef_getArraySize getting array size for %s", sRef_unparse(p_s) )  ));
9188   
9189   c = sRef_getType (p_s);
9190
9191   return (ctype_getArraySize (c) );
9192 }
9193
9194
9195
This page took 0.882076 seconds and 5 git commands to generate.