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