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