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