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