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