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