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