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