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