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