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