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