Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

sRef.c

Go to the documentation of this file.
00001 /*
00002 ** LCLint - annotation-assisted static program checker
00003 ** Copyright (C) 1994-2000 University of Virginia,
00004 **         Massachusetts Institute of Technology
00005 **
00006 ** This program is free software; you can redistribute it and/or modify it
00007 ** under the terms of the GNU General Public License as published by the
00008 ** Free Software Foundation; either version 2 of the License, or (at your
00009 ** option) any later version.
00010 ** 
00011 ** This program is distributed in the hope that it will be useful, but
00012 ** WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** General Public License for more details.
00015 ** 
00016 ** The GNU General Public License is available from http://www.gnu.org/ or
00017 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018 ** MA 02111-1307, USA.
00019 **
00020 ** For information on lclint: lclint-request@cs.virginia.edu
00021 ** To report a bug: lclint-bug@cs.virginia.edu
00022 ** For more information: http://lclint.cs.virginia.edu
00023 */
00024 /*
00025 ** storeRef.c
00026 **
00027 ** Memory management:
00028 **    storeRef's are kept in allRefs for each function scope, and all are
00029 **    free'd at the end of the function.  This relies on the constraint that
00030 **    no storeRef created while checking a function is used outside that
00031 **    function.
00032 **
00033 **    storeRefs in the file and global scopes are free'd by the uentry.
00034 **
00035 */
00036 
00037 # include "lclintMacros.nf"
00038 # include "basic.h"
00039 # include "exprChecks.h"
00040 # include "aliasChecks.h"
00041 # include "sRefTable.h"
00042 # include "structNames.h"
00043 
00044 /*
00045 ** Predicate functions that evaluate both arguments in order.
00046 */
00047 
00048 /*@notfunction@*/
00049 # define OR(a,b)  (a ? (b, TRUE) : b)
00050 
00051 /*@notfunction@*/
00052 # define AND(a,b) (a ? b : (b, FALSE))
00053 
00054 static bool sRef_isDerived (sRef p_s) /*@*/ ;
00055 
00056 static /*@exposed@*/ sRef sRef_fixDirectBase (sRef p_s, sRef p_base) 
00057    /*@modifies p_base@*/ ;
00058 
00059 static bool sRef_isAllocatedStorage (sRef p_s) /*@*/ ;
00060 static void sRef_setNullErrorLoc (sRef p_s, fileloc) /*@*/ ;
00061 
00062 static void
00063   sRef_aliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s, fileloc p_loc)
00064   /*@modifies p_s@*/ ;
00065 
00066 static int sRef_depth (sRef p_s) /*@*/ ;
00067 
00068 static void
00069   sRef_innerAliasSetComplete (void (p_predf) (sRef, fileloc), sRef p_s, 
00070                               fileloc p_loc)
00071   /*@modifies p_s@*/ ;
00072 
00073 static void
00074   sRef_innerAliasSetCompleteParam (void (p_predf) (sRef, sRef), sRef p_s, sRef p_t)
00075   /*@modifies p_s@*/ ;
00076 
00077 static void
00078   sRef_aliasSetCompleteParam (void (p_predf) (sRef, alkind, fileloc), sRef p_s, 
00079                               alkind p_kind, fileloc p_loc)
00080   /*@modifies p_s@*/ ;
00081 
00082 static speckind speckind_fromInt (int p_i);
00083 static bool sRef_equivalent (sRef p_s1, sRef p_s2);
00084 static bool sRef_isDeepUnionField (sRef p_s);
00085 static void sRef_addDeriv (/*@notnull@*/ sRef p_s, /*@notnull@*/ sRef p_t);
00086 static sRef sRef_makeResultType (ctype p_ct) /*@*/ ;
00087 static bool sRef_checkModify (sRef p_s, sRefSet p_sl) /*@*/ ;
00088 
00089 static bool skind_isSimple (skind sk)
00090 {
00091   switch (sk)
00092     {
00093     case SK_PARAM: case SK_CVAR: case SK_CONST:
00094     case SK_OBJECT: case SK_UNKNOWN: case SK_NEW:
00095       return TRUE;
00096     default:
00097       return FALSE;
00098     }
00099 }
00100 
00101 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef p_s)
00102    /*@uses p_s->kind, p_s->info@*/
00103    /*@releases p_s->info@*/ ;
00104 
00105 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef p_s) /*@*/ ;
00106 static void sRef_setPartsFromUentry (sRef p_s, uentry p_ue)
00107    /*@modifies p_s@*/ ;
00108 static bool checkDeadState (/*@notnull@*/ sRef p_el, bool p_tbranch, fileloc p_loc);
00109 static sRef sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef p_t) /*@*/ ;
00110 
00111 static void 
00112   sRef_combineExKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
00113   /*@modifies p_res@*/ ;
00114 
00115 static void 
00116   sRef_combineAliasKinds (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other, 
00117                           clause p_cl, fileloc p_loc)
00118   /*@modifies p_res@*/ ;
00119 
00120 static void
00121   sRef_combineNullState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
00122   /*@modifies p_res@*/ ;
00123 
00124 static void
00125   sRef_combineDefState (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other)
00126   /*@modifies p_res@*/ ;
00127 
00128 static void sRef_setStateFromAbstractUentry (sRef p_s, uentry p_ue) 
00129   /*@modifies p_s@*/ ;
00130 
00131 static void 
00132   sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef p_res, 
00133                 /*@notnull@*/ /*@exposed@*/ sRef p_other);
00134 static /*@only@*/ alinfo alinfo_makeRefLoc (/*@exposed@*/ sRef p_ref, fileloc p_loc);
00135 static void sRef_setDefinedAux (sRef p_s, fileloc p_loc, bool p_clear)
00136    /*@modifies p_s@*/ ;
00137 static void sRef_setDefinedNoClear (sRef p_s, fileloc p_loc)
00138    /*@modifies p_s@*/ ;
00139 static void sRef_setStateAux (sRef p_s, sstate p_ss, fileloc p_loc)
00140    /*@modifies p_s@*/;
00141 
00142 static /*@exposed@*/ sRef 
00143   sRef_buildNCField (/*@exposed@*/ sRef p_rec, /*@exposed@*/ cstring p_f);
00144 
00145 static void 
00146   sRef_mergeStateAux (/*@notnull@*/ sRef p_res, /*@notnull@*/ sRef p_other, 
00147                       clause p_cl, bool p_opt, fileloc p_loc,
00148                       bool p_doDerivs)
00149   /*@modifies p_res, p_other@*/ ;
00150 
00151 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef p_s);
00152 static bool sRef_doModify (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/ ;
00153 static bool sRef_doModifyVal (sRef p_s, sRefSet p_sl) /*@modifies p_s@*/;
00154 static bool sRef_checkModifyVal (sRef p_s, sRefSet p_sl) /*@*/ ;
00155 
00156 static /*@only@*/ sRefSet
00157   sRef_mergeDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, 
00158                     bool p_opt, clause p_cl, fileloc p_loc);
00159 
00160 static /*@only@*/ sRefSet
00161   sRef_mergeUnionDerivs (/*@only@*/ sRefSet p_res, 
00162                          /*@exposed@*/ sRefSet p_other,
00163                          bool p_opt, clause p_cl, fileloc p_loc);
00164 
00165 static /*@only@*/ sRefSet 
00166   sRef_mergePdefinedDerivs (/*@only@*/ sRefSet p_res, sRefSet p_other, bool p_opt,
00167                             clause p_cl, fileloc p_loc);
00168 
00169 static /*@only@*/ cstring sRef_unparseWithArgs (sRef p_s, uentryList p_args);
00170 static /*@only@*/ cstring sRef_unparseNoArgs (sRef p_s);
00171 
00172 static /*@exposed@*/ sRef sRef_findDerivedPointer (sRef p_s);
00173 static /*@exposed@*/ sRef sRef_findDerivedField (/*@notnull@*/ sRef p_rec, cstring p_f);
00174 static /*@exposed@*/ sRef
00175   sRef_getDeriv (/*@notnull@*/ /*@returned@*/ sRef p_set, sRef p_guide);
00176 
00177 static bool inFunction = FALSE;
00178 static /*@only@*/ sRefTable allRefs;
00179 
00180 /* # define DEBUGREFS  */
00181 
00182 # ifdef DEBUGREFS
00183 static nsrefs = 0;
00184 static totnsrefs = 0;
00185 static maxnsrefs = 0;
00186 static ntotrefers = 0;
00187 static nrefers = 0;
00188 # endif
00189 
00190 /*@constant null alinfo alinfo_undefined; @*/
00191 # define alinfo_undefined ((alinfo) NULL)
00192 
00193 static /*@only@*/ /*@notnull@*/ alinfo alinfo_makeLoc (fileloc p_loc);
00194 static /*@only@*/ alinfo alinfo_copy (alinfo p_a);
00195 
00196 static /*@checked@*/ bool protectDerivs = FALSE;
00197 
00198 void sRef_protectDerivs (void) /*@modifies protectDerivs@*/
00199 {
00200   llassert (!protectDerivs);
00201   protectDerivs = TRUE;
00202 }
00203 
00204 void sRef_clearProtectDerivs (void) /*@modifies protectDerivs@*/
00205 {
00206   llassert (protectDerivs);
00207   protectDerivs = FALSE;
00208 }
00209 
00210 /*
00211 ** hmmm...here be kind of a hack.  This function mysteriously appeared
00212 ** in my code, but I'm sure I didn't write it.
00213 */
00214 
00215 bool
00216 sRef_isRecursiveField (sRef s)
00217 {
00218   if (sRef_isField (s))
00219     {
00220       if (sRef_depth (s) > 13)
00221         {
00222           sRef base;
00223           cstring fieldname;
00224           
00225           fieldname = sRef_getField (s);
00226           base = sRef_getBase (s);
00227           
00228           while (sRef_isValid (base))
00229             {
00230               if (sRef_isField (base))
00231                 {
00232                   if (cstring_equal (fieldname, sRef_getField (base)))
00233                     {
00234                       return TRUE;
00235                     }
00236                 }
00237               
00238               base = sRef_getBaseSafe (base);
00239             }
00240         }
00241     }
00242 
00243   return FALSE;
00244 }
00245 
00246 static void
00247 sRef_addDeriv (/*@notnull@*/ sRef s, /*@notnull@*/ sRef t)
00248 {
00249   if (!context_inProtectVars () 
00250       && !protectDerivs
00251       && sRef_isValid (s)
00252       && sRef_isValid (t)
00253       && !sRef_isConst (s))
00254     {
00255       int sd = sRef_depth (s);
00256       int td = sRef_depth (t);
00257       
00258       if (sd >= td)
00259         {
00260           return;
00261         }
00262 
00263       if (sRef_isGlobal (s))
00264         {
00265           if (context_inFunctionLike () 
00266               && ctype_isKnown (sRef_getType (s))
00267               && !ctype_isFunction (sRef_getType (s)))
00268             {
00269               globSet g = context_getUsedGlobs ();
00270 
00271               if (!globSet_member (g, s))
00272                 {
00273                   /* 
00274                   ** don't report as a bug 
00275                   ** 
00276 
00277                   llcontbug 
00278                         (message ("sRef_addDeriv: global variable not in used "
00279                                   "globs: %q / %s / %q",
00280                                   sRef_unparse (s), 
00281                                   ctype_unparse (sRef_getType (s)),
00282                                   sRefSet_unparse (s->deriv)));
00283                   */
00284                 }
00285               else
00286                 {
00287                   s->deriv = sRefSet_insert (s->deriv, t);
00288                 }
00289             }
00290         }
00291       else
00292         {
00293           s->deriv = sRefSet_insert (s->deriv, t);
00294         }
00295     }
00296 }
00297 
00298 bool
00299 sRef_deepPred (bool (predf) (sRef), sRef s)
00300 {
00301   if (sRef_isValid (s))
00302     {
00303       if ((*predf)(s)) return TRUE;
00304 
00305       switch  (s->kind)
00306         {
00307         case SK_PTR:
00308           return (sRef_deepPred (predf, s->info->ref));
00309         case SK_ARRAYFETCH:
00310           return (sRef_deepPred (predf, s->info->arrayfetch->arr));
00311         case SK_FIELD:
00312           return (sRef_deepPred (predf, s->info->field->rec));
00313         case SK_CONJ:
00314           return (sRef_deepPred (predf, s->info->conj->a)
00315                   || sRef_deepPred (predf, s->info->conj->b));
00316         default:
00317           return FALSE;
00318         }
00319     }
00320 
00321   return FALSE;
00322 }
00323 
00324 bool sRef_modInFunction (void)
00325 {
00326   return inFunction;
00327 }
00328 
00329 void sRef_setStateFromType (sRef s, ctype ct)
00330 {
00331   if (sRef_isValid (s))
00332     {
00333       if (ctype_isUser (ct))
00334         {
00335           sRef_setStateFromUentry 
00336             (s, usymtab_getTypeEntry (ctype_typeId (ct)));
00337         }
00338       else if (ctype_isAbstract (ct))
00339         {
00340           sRef_setStateFromAbstractUentry 
00341             (s, usymtab_getTypeEntry (ctype_typeId (ct)));
00342         }
00343       else
00344         {
00345           ; /* not a user type */
00346         }
00347     }
00348 }
00349 
00350 static void sRef_setTypeState (sRef s)
00351 {
00352   if (sRef_isValid (s))
00353     {
00354       sRef_setStateFromType (s, s->type);
00355     }
00356 }
00357 
00358 static void alinfo_free (/*@only@*/ alinfo a)
00359 {
00360   if (a != NULL)
00361     {
00362       fileloc_free (a->loc);
00363       sfree (a);
00364     }
00365 }
00366 
00367 static /*@only@*/ alinfo alinfo_update (/*@only@*/ alinfo old, alinfo newinfo)
00368 /*
00369 ** returns an alinfo with the same value as new.  May reuse the
00370 ** storage of old.  (i.e., same effect as copy, but more
00371 ** efficient.)
00372 */
00373 {
00374   if (old == NULL) 
00375     {
00376       old = alinfo_copy (newinfo);
00377     }
00378   else if (newinfo == NULL)
00379     {
00380       alinfo_free (old);
00381       return NULL;
00382     }
00383   else
00384     {
00385       old->loc = fileloc_update (old->loc, newinfo->loc);
00386       old->ref = newinfo->ref;
00387       old->ue = newinfo->ue;
00388     }
00389 
00390   return old;
00391 }
00392 
00393 static /*@only@*/ alinfo alinfo_updateLoc (/*@only@*/ alinfo old, fileloc loc)
00394 {
00395   if (old == NULL) 
00396     {
00397       old = alinfo_makeLoc (loc);
00398     }
00399   else
00400     {
00401       old->loc = fileloc_update (old->loc, loc);
00402       old->ue = uentry_undefined;
00403       old->ref = sRef_undefined;
00404     }
00405 
00406   return old;
00407 }
00408 
00409 static /*@only@*/ alinfo 
00410   alinfo_updateRefLoc (/*@only@*/ alinfo old, /*@dependent@*/ sRef ref, fileloc loc)
00411 {
00412   if (old == NULL) 
00413     {
00414       old = alinfo_makeRefLoc (ref, loc);
00415     }
00416   else
00417     {
00418       old->loc = fileloc_update (old->loc, loc);
00419       old->ue = uentry_undefined;
00420       old->ref = ref;
00421     }
00422 
00423   return old;
00424 }
00425 
00426 static /*@only@*/ alinfo
00427 alinfo_copy (alinfo a)
00428 {
00429   if (a == NULL)
00430     {
00431       return NULL;
00432     }
00433   else
00434     {
00435       alinfo ret = (alinfo) dmalloc (sizeof (*ret));
00436       
00437       ret->loc = fileloc_copy (a->loc); /*< should report bug without copy! >*/
00438       ret->ue = a->ue;
00439       ret->ref = a->ref;
00440 
00441       return ret;
00442     }
00443 }
00444 
00445 static bool
00446   sRef_hasAliasInfoLoc (sRef s)
00447 {
00448   return (sRef_isValid (s) && (s->aliasinfo != NULL)
00449           && (fileloc_isDefined (s->aliasinfo->loc)));
00450 }
00451 
00452 static /*@falsenull@*/ bool
00453 sRef_hasStateInfoLoc (sRef s)
00454 {
00455   return (sRef_isValid (s) && (s->definfo != NULL) 
00456           && (fileloc_isDefined (s->definfo->loc)));
00457 }
00458 
00459 static /*@falsenull@*/ bool
00460 sRef_hasExpInfoLoc (sRef s)
00461 {
00462   return (sRef_isValid (s) 
00463           && (s->expinfo != NULL) && (fileloc_isDefined (s->expinfo->loc)));
00464 }
00465 
00466 static bool
00467 sRef_hasNullInfoLoc (sRef s)
00468 {
00469   return (sRef_isValid (s) && (s->nullinfo != NULL) 
00470           && (fileloc_isDefined (s->nullinfo->loc)));
00471 }
00472 
00473 bool
00474 sRef_hasAliasInfoRef (sRef s)
00475 {
00476   return (sRef_isValid (s) && (s->aliasinfo != NULL) 
00477           && (sRef_isValid (s->aliasinfo->ref)));
00478 }
00479 
00480 static /*@observer@*/ fileloc
00481 sRef_getAliasInfoLoc (/*@exposed@*/ sRef s)
00482 {
00483   llassert (sRef_isValid (s) && s->aliasinfo != NULL
00484             && (fileloc_isDefined (s->aliasinfo->loc)));
00485   return (s->aliasinfo->loc);
00486 }
00487 
00488 static /*@observer@*/ fileloc
00489 sRef_getStateInfoLoc (/*@exposed@*/ sRef s)
00490 {
00491   llassert (sRef_isValid (s) && s->definfo != NULL 
00492             && (fileloc_isDefined (s->definfo->loc)));
00493   return (s->definfo->loc);
00494 }
00495 
00496 static /*@observer@*/ fileloc
00497 sRef_getExpInfoLoc (/*@exposed@*/ sRef s)
00498 {
00499   llassert (sRef_isValid (s) && s->expinfo != NULL 
00500             && (fileloc_isDefined (s->expinfo->loc)));
00501   return (s->expinfo->loc);
00502 }
00503 
00504 static /*@observer@*/ fileloc
00505 sRef_getNullInfoLoc (/*@exposed@*/ sRef s)
00506 {
00507   llassert (sRef_isValid (s) && s->nullinfo != NULL 
00508             && (fileloc_isDefined (s->nullinfo->loc)));
00509   return (s->nullinfo->loc);
00510 }
00511 
00512 /*@observer@*/ sRef
00513   sRef_getAliasInfoRef (/*@exposed@*/ sRef s)
00514 {
00515   llassert (sRef_isValid (s) && s->aliasinfo != NULL);
00516   return (s->aliasinfo->ref);
00517 }
00518 
00519 static /*@only@*/ /*@notnull@*/ alinfo
00520 alinfo_makeLoc (fileloc loc)
00521 {
00522   alinfo ret = (alinfo) dmalloc (sizeof (*ret));
00523 
00524   ret->loc = fileloc_copy (loc); /* don't need to copy! */
00525   ret->ue = uentry_undefined;
00526   ret->ref = sRef_undefined;
00527   
00528   return ret;
00529 }
00530 
00531 static /*@only@*/ alinfo
00532 alinfo_makeRefLoc (/*@exposed@*/ sRef ref, fileloc loc)
00533 {
00534   alinfo ret = (alinfo) dmalloc (sizeof (*ret));
00535 
00536   ret->loc = fileloc_copy (loc);
00537   ret->ref = ref;
00538   ret->ue  = uentry_undefined;
00539   
00540   return ret;
00541 }
00542 
00543 /*
00544 ** This function should be called before new sRefs are created
00545 ** somewhere where they will have a lifetime greater than the
00546 ** current function scope.
00547 */
00548 
00549 void sRef_setGlobalScope ()
00550 {
00551   llassert (inFunction);
00552   inFunction = FALSE;
00553 }
00554 
00555 void sRef_clearGlobalScope ()
00556 {
00557   llassert (!inFunction);
00558   inFunction = TRUE;
00559 }
00560 
00561 static bool oldInFunction = FALSE;
00562 
00563 void sRef_setGlobalScopeSafe ()
00564 {
00565     oldInFunction = inFunction;
00566   inFunction = FALSE;
00567 }
00568 
00569 void sRef_clearGlobalScopeSafe ()
00570 {
00571     inFunction = oldInFunction;
00572 }
00573 
00574 void sRef_enterFunctionScope ()
00575 {
00576   llassert (!inFunction);
00577   llassert (sRefTable_isEmpty (allRefs));
00578   inFunction = TRUE;
00579 }
00580 
00581 void sRef_exitFunctionScope ()
00582 {
00583   
00584   if (inFunction)
00585     {
00586       sRefTable_clear (allRefs);
00587       inFunction = FALSE;
00588     }
00589   else
00590     {
00591       llbuglit ("sRef_exitFunctionScope: not in function");
00592     }
00593 }
00594   
00595 void sRef_destroyMod () /*@globals killed allRefs;@*/
00596 {
00597 # ifdef DEBUGREFS  
00598   llmsg (message ("Live: %d / %d ", nsrefs, totnsrefs));  
00599 # endif
00600 
00601   sRefTable_free (allRefs);
00602 }
00603 
00604 /*
00605 ** Result of sRef_alloc is dependent since allRefs may
00606 ** reference it.  It is only if !inFunction.
00607 */
00608 
00609 static /*@dependent@*/ /*@out@*/ /*@notnull@*/ sRef
00610 sRef_alloc (void)
00611 {
00612   sRef s = (sRef) dmalloc (sizeof (*s));
00613 
00614   if (inFunction)
00615     {
00616       allRefs = sRefTable_add (allRefs, s);
00617       /*@-branchstate@*/ 
00618     } 
00619   /*@=branchstate@*/
00620 
00621 # ifdef DEBUGREFS
00622   if (nsrefs >= maxnsrefs)
00623     {
00624       maxnsrefs = nsrefs;
00625     }
00626 
00627   totnsrefs++;
00628   nsrefs++;
00629 # endif
00630 
00631   /*@-mustfree@*/ /*@-freshtrans@*/
00632   return s;
00633   /*@=mustfree@*/ /*@=freshtrans@*/
00634 }
00635 
00636 static /*@dependent@*/ /*@notnull@*/ /*@special@*/ sRef
00637   sRef_new (void)
00638   /*@defines result@*/
00639   /*@post:isnull result->aliasinfo, result->definfo, result->nullinfo, 
00640                  result->expinfo, result->info, result->deriv@*/
00641 {
00642   sRef s = sRef_alloc ();
00643 
00644   s->kind = SK_UNKNOWN;
00645   s->safe = TRUE;
00646   s->modified = FALSE;
00647   s->type = ctype_unknown;
00648   s->defstate = SS_UNKNOWN;
00649 
00650   s->aliaskind = AK_UNKNOWN;
00651   s->oaliaskind = AK_UNKNOWN;
00652 
00653   s->nullstate = NS_UNKNOWN;
00654 
00655   s->expkind = XO_UNKNOWN;
00656   s->oexpkind = XO_UNKNOWN;
00657 
00658   s->aliasinfo = alinfo_undefined;
00659   s->definfo = alinfo_undefined;
00660   s->nullinfo = alinfo_undefined;
00661   s->expinfo = alinfo_undefined;
00662 
00663   s->info = NULL;
00664   s->deriv = sRefSet_undefined;
00665 
00666   return s;
00667 }
00668 
00669 static /*@notnull@*/ /*@exposed@*/ sRef
00670 sRef_fixConj (/*@notnull@*/ sRef s)
00671 {
00672   if (sRef_isConj (s))
00673     {
00674       do {
00675         s = sRef_getConjA (s);
00676       } while (sRef_isConj (s));
00677       
00678       llassert (sRef_isValid (s));
00679       return s; /* don't need to ref */
00680     }
00681   else
00682     {
00683       return s;
00684     }
00685 }
00686 
00687 static bool 
00688 sRef_isExternallyVisibleAux (sRef s)
00689 {
00690   bool res = FALSE;
00691   sRef base = sRef_getRootBase (s);
00692 
00693   if (sRef_isValid (base))
00694     {
00695       res = sRef_isParam (base) || sRef_isGlobal (base) || sRef_isExternal (base);
00696     }
00697 
00698   return res;
00699 }
00700 
00701 bool 
00702   sRef_isExternallyVisible (sRef s)
00703 {
00704   return (sRef_aliasCheckSimplePred (sRef_isExternallyVisibleAux, s));
00705 }
00706 
00707 /*@exposed@*/ uentry
00708 sRef_getBaseUentry (sRef s)
00709 {
00710   sRef base = sRef_getRootBase (s);
00711   uentry res = uentry_undefined;
00712   
00713   if (sRef_isValid (base))
00714     {
00715       switch (base->kind)
00716         {
00717         case SK_PARAM:
00718           res = usymtab_getRefQuiet (paramsScope, base->info->paramno);
00719           break;
00720 
00721         case SK_CVAR:
00722           res = usymtab_getRefQuiet (base->info->cvar->lexlevel, 
00723                                      base->info->cvar->index);
00724           break;
00725 
00726         default:
00727           break;
00728         }  
00729     }
00730 
00731   return res;
00732 }
00733 
00734 /*
00735 ** lookup the current uentry corresponding to s, and return the corresponding sRef.
00736 ** yuk yuk yuk yuk yuk yuk yuk yuk
00737 */
00738 
00739 /*@exposed@*/ sRef
00740 sRef_updateSref (sRef s)
00741 {
00742   sRef inner;
00743   sRef ret;
00744   sRef res;
00745 
00746   if (!sRef_isValid (s)) return sRef_undefined;
00747 
00748   
00749   switch (s->kind)
00750     {
00751     case SK_UNKNOWN:
00752     case SK_OBJECT:
00753     case SK_NEW:
00754     case SK_TYPE:
00755     case SK_EXTERNAL:
00756     case SK_DERIVED:
00757     case SK_UNCONSTRAINED:
00758     case SK_CONST:
00759     case SK_SPECIAL:
00760     case SK_RESULT:
00761       return s; 
00762     case SK_PARAM:
00763     case SK_CVAR:
00764       {
00765         uentry ue = sRef_getUentry (s);
00766 
00767         /* must be raw name!  (need the marker) */
00768         ue = usymtab_lookupSafe (uentry_rawName (ue));
00769         
00770         if (uentry_isUndefined (ue))
00771           {
00772                     return s;
00773           }
00774         else
00775           {
00776                     return (uentry_getSref (ue));
00777           }
00778       }
00779     case SK_ARRAYFETCH:
00780       /* special case if ind known */
00781       inner = s->info->arrayfetch->arr;
00782       ret = sRef_updateSref (inner);
00783 
00784       if (ret == inner) 
00785         {
00786           res = s; 
00787         }
00788       else 
00789         {
00790           res = sRef_makeArrayFetch (ret);
00791         }
00792 
00793       return res;
00794 
00795     case SK_FIELD:
00796       inner = s->info->field->rec;
00797       ret = sRef_updateSref (inner);
00798 
00799       if (ret == inner) 
00800         {
00801           res = s; 
00802         }
00803       else 
00804         {
00805           res = (sRef_makeField (ret, s->info->field->field));
00806         }
00807 
00808       return (res);
00809     case SK_PTR:
00810       inner = s->info->ref;
00811       ret = sRef_updateSref (inner);
00812       if (ret == inner) 
00813         {
00814           res = s; 
00815         }
00816       else
00817         {
00818           res = sRef_makePointer (ret);
00819         }
00820 
00821       return (res);
00822 
00823     case SK_ADR:
00824       inner = s->info->ref;
00825       ret = sRef_updateSref (inner);
00826 
00827       if (ret == inner)
00828         {
00829           res = s; 
00830         }
00831       else 
00832         {
00833           res = sRef_makeAddress (ret);
00834         }
00835 
00836       return (res);
00837 
00838     case SK_CONJ:
00839       {
00840         sRef innera = s->info->conj->a;
00841         sRef innerb = s->info->conj->b;
00842         sRef reta = sRef_updateSref (innera);
00843         sRef retb = sRef_updateSref (innerb);
00844 
00845         if (innera == reta && innerb == retb)
00846           {
00847             res = s;
00848           }
00849         else 
00850           {
00851             res = sRef_makeConj (reta, retb);
00852           }
00853 
00854         return (res);
00855       }
00856     }
00857   
00858   BADEXIT;
00859 }
00860 
00861 uentry
00862 sRef_getUentry (sRef s)
00863 {
00864   llassert (sRef_isValid (s));
00865 
00866   switch (s->kind)
00867     {
00868     case SK_PARAM:
00869       return (usymtab_getRefQuiet (paramsScope, s->info->paramno));
00870     case SK_CVAR:
00871       return (usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index));
00872     case SK_CONJ:
00873       {
00874         if (sRef_isCvar (s->info->conj->a) || sRef_isParam (s->info->conj->a)
00875             || sRef_isConj (s->info->conj->a))
00876           {
00877             return sRef_getUentry (s->info->conj->a);
00878           }
00879         else 
00880           {
00881             return sRef_getUentry (s->info->conj->b);
00882           }
00883       }
00884     case SK_UNKNOWN:
00885     case SK_SPECIAL:
00886       return uentry_undefined;
00887     BADDEFAULT;
00888     }
00889 }
00890 
00891 int
00892 sRef_getParam (sRef s)
00893 {
00894   llassert (sRef_isValid (s));
00895   llassert (s->kind == SK_PARAM);
00896 
00897   return s->info->paramno;
00898 }
00899 
00900 bool
00901 sRef_isModified (sRef s)
00902 {
00903     return (!sRef_isValid (s) || s->modified);
00904 }
00905 
00906 void sRef_setModified (sRef s)
00907 {
00908   if (sRef_isValid (s))
00909     {
00910       s->modified = TRUE;
00911 
00912       
00913       if (sRef_isRefsField (s))
00914         {
00915           sRef base = sRef_getBase (s);
00916 
00917           
00918           llassert (s->kind == SK_FIELD);
00919 
00920           
00921           if (sRef_isPointer (base))
00922             {
00923               base = sRef_getBase (base);
00924                     }
00925 
00926           if (sRef_isRefCounted (base))
00927             {
00928               base->aliaskind = AK_NEWREF;
00929                     }
00930         }
00931 
00932           }
00933 }
00934 
00935 /*
00936 ** note: this side-effects sRefSet to set modified to TRUE
00937 ** for any sRef similar to s.
00938 */
00939 
00940 bool
00941 sRef_canModifyVal (sRef s, sRefSet sl)
00942 {
00943   if (context_getFlag (FLG_MUSTMOD))
00944     {
00945       return (sRef_doModifyVal (s, sl));
00946     }
00947   else
00948     {
00949       return (sRef_checkModifyVal (s, sl));
00950     }
00951 }
00952 
00953 bool
00954 sRef_canModify (sRef s, sRefSet sl)
00955 {
00956   
00957   if (context_getFlag (FLG_MUSTMOD))
00958     {
00959       return (sRef_doModify (s, sl));
00960     }
00961   else
00962     {
00963       return (sRef_checkModify (s, sl));
00964     }
00965 }
00966 
00967 /*
00968 ** No side-effects
00969 */
00970 
00971 static
00972 bool sRef_checkModifyVal (sRef s, sRefSet sl)
00973 {
00974   if (sRef_isInvalid (s))
00975     {
00976       return TRUE;
00977     }
00978   
00979   switch (s->kind)
00980     {
00981     case SK_UNCONSTRAINED:
00982     case SK_CONST:
00983       return TRUE;
00984     case SK_CVAR:
00985       if (sRef_isGlobal (s))
00986         {
00987           if (context_checkGlobMod (s))
00988             {
00989               return (sRefSet_member (sl, s));
00990             }
00991 
00992           return TRUE;
00993         }
00994       else
00995         {
00996           return TRUE;
00997         }
00998     case SK_PARAM:
00999             return (sRefSet_member (sl, s) 
01000               || alkind_isOnly (sRef_getOrigAliasKind (s)));
01001     case SK_ARRAYFETCH: 
01002       /* special case if ind known */
01003       return (sRefSet_member (sl, s) ||
01004               sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
01005     case SK_FIELD:
01006       return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
01007     case SK_PTR:
01008       return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
01009     case SK_ADR:
01010       return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
01011     case SK_CONJ:
01012       return ((sRef_checkModifyVal (s->info->conj->a, sl)) &&
01013               (sRef_checkModifyVal (s->info->conj->b, sl)));
01014     case SK_UNKNOWN:
01015     case SK_OBJECT:
01016     case SK_NEW:
01017     case SK_TYPE:
01018     case SK_DERIVED:
01019       return TRUE;
01020     case SK_EXTERNAL:
01021       return TRUE;
01022     case SK_SPECIAL:
01023       {
01024         switch (s->info->spec)
01025           {
01026           case SR_NOTHING:   return TRUE;
01027           case SR_INTERNAL:  
01028             if (context_getFlag (FLG_INTERNALGLOBS))
01029               {
01030                 return (sRefSet_member (sl, s));
01031               }
01032             else
01033               {
01034                 return TRUE;
01035               }
01036           case SR_SPECSTATE: return TRUE;
01037           case SR_SYSTEM:    return (sRefSet_member (sl, s));
01038           }
01039       }
01040     case SK_RESULT: BADBRANCH;
01041     }
01042   BADEXIT;
01043 }
01044 
01045 /*
01046 ** this should probably be elsewhere...
01047 **
01048 ** returns TRUE iff sl indicates that s can be modified
01049 */
01050 
01051 static bool sRef_checkModify (sRef s, sRefSet sl)
01052 {
01053   llassert (sRef_isValid (s));
01054 
01055   switch (s->kind)
01056     {
01057     case SK_UNCONSTRAINED:
01058     case SK_CONST:
01059       return TRUE;
01060     case SK_CVAR:
01061       if (sRef_isGlobal (s))
01062         {
01063           if (context_checkGlobMod (s))
01064             {
01065               return (sRefSet_member (sl, s));
01066             }
01067 
01068           return TRUE;
01069         }
01070       else
01071         {
01072           return TRUE;
01073         }
01074     case SK_PARAM:
01075       return TRUE;
01076     case SK_ARRAYFETCH:
01077       return (sRefSet_member (sl, s) ||
01078               sRef_checkModifyVal (s->info->arrayfetch->arr, sl));
01079     case SK_FIELD:
01080       {
01081         sRef sr = s->info->field->rec;
01082 
01083         if (sr->kind == SK_PARAM)
01084           return TRUE; /* structs are copied on call */
01085 
01086         return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->field->rec, sl));
01087       }
01088     case SK_PTR:
01089       {
01090         bool sm;
01091 
01092         sm = sRefSet_member (sl, s);
01093 
01094         if (sm)
01095           return TRUE;
01096         else
01097           return (sRef_checkModifyVal (s->info->ref, sl));
01098       }
01099     case SK_ADR:
01100       return (sRefSet_member (sl, s) || sRef_checkModifyVal (s->info->ref, sl));
01101     case SK_CONJ:
01102       return ((sRef_checkModify (s->info->conj->a, sl)) &&
01103               (sRef_checkModify (s->info->conj->b, sl)));
01104     case SK_NEW:
01105     case SK_OBJECT:
01106     case SK_UNKNOWN:
01107     case SK_TYPE:
01108     case SK_DERIVED:
01109     case SK_EXTERNAL:
01110       return TRUE;
01111     case SK_SPECIAL:
01112       {
01113         switch (s->info->spec)
01114           {
01115           case SR_NOTHING:   return TRUE;
01116           case SR_INTERNAL:  
01117             if (context_getFlag (FLG_INTERNALGLOBS))
01118               {
01119                 return (sRefSet_member (sl, s));
01120               }
01121             else
01122               {
01123                 return TRUE;
01124               }
01125           case SR_SPECSTATE: return TRUE;
01126           case SR_SYSTEM:    return (sRefSet_member (sl, s));
01127           }
01128       }
01129     case SK_RESULT: BADBRANCH;
01130     }
01131   BADEXIT;
01132 }
01133 
01134 cstring sRef_stateVerb (sRef s)
01135 {
01136   if (sRef_isDead (s))
01137     {
01138       return cstring_makeLiteralTemp ("released");
01139     }
01140   else if (sRef_isKept (s))
01141     {
01142       return cstring_makeLiteralTemp ("kept");
01143     }
01144   else if (sRef_isDependent (s))
01145     {
01146       return cstring_makeLiteralTemp ("dependent");
01147     }
01148   else
01149     {
01150       BADEXIT;
01151     }
01152 }
01153 
01154 cstring sRef_stateAltVerb (sRef s)
01155 {
01156   if (sRef_isDead (s))
01157     {
01158       return cstring_makeLiteralTemp ("live");
01159     }
01160   else if (sRef_isKept (s))
01161     {
01162       return cstring_makeLiteralTemp ("not kept");
01163     }
01164   else if (sRef_isDependent (s))
01165     {
01166       return cstring_makeLiteralTemp ("independent");
01167     }
01168   else
01169     {
01170       BADEXIT;
01171     }
01172 }
01173 
01174 static 
01175 bool sRef_doModifyVal (sRef s, sRefSet sl)
01176 {
01177   llassert (sRef_isValid (s));
01178 
01179   
01180   switch (s->kind)
01181     {
01182     case SK_UNCONSTRAINED:
01183     case SK_CONST:
01184       return TRUE;
01185     case SK_CVAR:
01186       if (sRef_isGlobal (s))
01187         {
01188           
01189           if (context_checkGlobMod (s))
01190             {
01191               return (sRefSet_modifyMember (sl, s));
01192             }
01193           else
01194             {
01195               (void) sRefSet_modifyMember (sl, s);
01196             }
01197 
01198                   return TRUE;
01199         }
01200       else
01201         {
01202           return TRUE;
01203         }      
01204     case SK_PARAM:
01205       return (sRefSet_modifyMember (sl, s) 
01206               || alkind_isOnly (sRef_getOrigAliasKind (s)));
01207     case SK_ARRAYFETCH:
01208       /* special case if ind known */
01209       /* unconditional OR, need side effect */
01210       return (OR (sRefSet_modifyMember (sl, s),
01211                   sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
01212     case SK_FIELD:
01213       return (OR (sRefSet_modifyMember (sl, s),
01214                   sRef_doModifyVal (s->info->field->rec, sl)));
01215     case SK_PTR:
01216       return (OR (sRefSet_modifyMember (sl, s),
01217                   sRef_doModifyVal (s->info->ref, sl)));
01218     case SK_ADR:
01219       return (OR (sRefSet_modifyMember (sl, s),
01220                   sRef_doModifyVal (s->info->ref, sl)));
01221     case SK_CONJ:
01222       return (AND (sRef_doModifyVal (s->info->conj->a, sl) ,
01223                    sRef_doModifyVal (s->info->conj->b, sl)));
01224     case SK_OBJECT:
01225     case SK_DERIVED:
01226     case SK_EXTERNAL:
01227     case SK_UNKNOWN:
01228     case SK_NEW:
01229     case SK_TYPE:
01230       return TRUE;
01231     case SK_SPECIAL:
01232       {
01233         switch (s->info->spec)
01234           {
01235           case SR_NOTHING:   return TRUE;
01236           case SR_INTERNAL:  
01237             if (context_getFlag (FLG_INTERNALGLOBS))
01238               {
01239                 return (sRefSet_modifyMember (sl, s));
01240               }
01241             else
01242               {
01243                 (void) sRefSet_modifyMember (sl, s);
01244                 return TRUE;
01245               }
01246           case SR_SPECSTATE: 
01247             {
01248               return TRUE;
01249             }
01250           case SR_SYSTEM:
01251             {
01252               return (sRefSet_modifyMember (sl, s));
01253             }
01254           }
01255       }
01256     case SK_RESULT: BADBRANCH;
01257     }
01258   BADEXIT;
01259 }
01260 
01261 /*
01262 ** this should probably be elsewhere...
01263 **
01264 ** returns TRUE iff sl indicates that s can be modified
01265 */
01266 
01267 static 
01268 bool sRef_doModify (sRef s, sRefSet sl)
01269 {
01270     llassert (sRef_isValid (s));
01271   
01272   switch (s->kind)
01273     {
01274     case SK_UNCONSTRAINED:
01275     case SK_CONST:
01276       return TRUE;
01277     case SK_CVAR:
01278       if (sRef_isGlobal (s))
01279         {
01280           if (context_checkGlobMod (s))
01281             {
01282               return (sRefSet_modifyMember (sl, s));
01283             }
01284           else
01285             {
01286               (void) sRefSet_modifyMember (sl, s);
01287             }
01288 
01289           return TRUE;
01290         }
01291       else
01292         {
01293           return TRUE;
01294         }
01295     case SK_PARAM:
01296       return TRUE;
01297     case SK_ARRAYFETCH:
01298             return (OR (sRefSet_modifyMember (sl, s),
01299                   sRef_doModifyVal (s->info->arrayfetch->arr, sl)));
01300     case SK_FIELD:
01301       {
01302         sRef sr = s->info->field->rec;
01303 
01304         if (sr->kind == SK_PARAM)
01305           {
01306             return TRUE; /* structs are shallow-copied on call */
01307           }
01308         
01309         return (OR (sRefSet_modifyMember (sl, s),
01310                     sRef_doModifyVal (s->info->field->rec, sl)));
01311       }
01312     case SK_PTR:
01313       {
01314         return (OR (sRefSet_modifyMember (sl, s),
01315                     sRef_doModifyVal (s->info->ref, sl)));
01316       }
01317     case SK_ADR:
01318       return (OR (sRefSet_modifyMember (sl, s),
01319                   sRef_doModifyVal (s->info->ref, sl)));
01320     case SK_CONJ:
01321       return (AND (sRef_doModify (s->info->conj->a, sl),
01322                   (sRef_doModify (s->info->conj->b, sl))));
01323     case SK_UNKNOWN:
01324     case SK_NEW:
01325     case SK_TYPE:
01326       return TRUE;
01327     case SK_OBJECT:
01328     case SK_DERIVED:
01329     case SK_EXTERNAL:
01330       return TRUE;
01331     case SK_SPECIAL:
01332       {
01333         switch (s->info->spec)
01334           {
01335           case SR_NOTHING:   return TRUE;
01336           case SR_INTERNAL:  return TRUE;
01337           case SR_SPECSTATE: return TRUE;
01338           case SR_SYSTEM:    return (sRefSet_modifyMember (sl, s));
01339           }
01340       }
01341     case SK_RESULT: BADBRANCH;
01342     }
01343   BADEXIT;
01344 }
01345 
01346 static /*@exposed@*/ sRef
01347   sRef_leastCommon (/*@exposed@*/ sRef s1, sRef s2)
01348 {
01349   llassert (sRef_similar (s1, s2));
01350   
01351   if (!sRef_isValid (s1)) return s1;
01352   if (!sRef_isValid (s2)) return s1;
01353 
01354   sRef_combineDefState (s1, s2);
01355   sRef_combineNullState (s1, s2);
01356   sRef_combineExKinds (s1, s2);
01357   
01358   if (s1->aliaskind != s2->aliaskind)
01359     {
01360       if (s1->aliaskind == AK_UNKNOWN)
01361         {
01362           s1->aliaskind = s2->aliaskind;
01363         }
01364       else if (s2->aliaskind == AK_UNKNOWN)
01365         {
01366           ;
01367         }
01368       else
01369         {
01370           s1->aliaskind = AK_ERROR;
01371         }
01372     }
01373 
01374   return s1;
01375 }
01376 
01377 int sRef_compare (sRef s1, sRef s2)
01378 {
01379   if (s1 == s2) return 0;
01380 
01381   if (sRef_isInvalid (s1)) return -1;
01382   if (sRef_isInvalid (s2)) return 1;
01383       
01384   INTCOMPARERETURN (s1->kind, s2->kind);
01385   INTCOMPARERETURN (s1->defstate, s2->defstate);
01386   INTCOMPARERETURN (s1->aliaskind, s2->aliaskind);
01387 
01388   COMPARERETURN (nstate_compare (s1->nullstate, s2->nullstate));
01389 
01390   switch (s1->kind)
01391     {
01392     case SK_PARAM:
01393       return (int_compare (s1->info->paramno, s2->info->paramno));
01394     case SK_ARRAYFETCH:
01395       {
01396         COMPARERETURN (sRef_compare (s1->info->arrayfetch->arr, 
01397                                      s2->info->arrayfetch->arr));
01398         
01399         if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
01400           {
01401             return (int_compare (s1->info->arrayfetch->ind, 
01402                                  s2->info->arrayfetch->ind));
01403           }
01404         if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
01405           return 0;
01406         
01407         return 1;
01408       }
01409     case SK_FIELD:
01410       {
01411         COMPARERETURN (sRef_compare (s1->info->field->rec, s2->info->field->rec));
01412         
01413         if (cstring_equal (s1->info->field->field, s2->info->field->field))
01414           return 0;
01415 
01416         return 1;
01417       }
01418     case SK_PTR:
01419     case SK_ADR:
01420       return (sRef_compare (s1->info->ref, s2->info->ref));
01421     case SK_CONJ:
01422       COMPARERETURN (sRef_compare (s1->info->conj->a, s2->info->conj->a));
01423       return (sRef_compare (s1->info->conj->b, s2->info->conj->b));
01424     case SK_UNCONSTRAINED:
01425       return (cstring_compare (s1->info->fname, s2->info->fname));
01426     case SK_NEW:
01427     case SK_CVAR:
01428     case SK_UNKNOWN:
01429     case SK_OBJECT:
01430     case SK_TYPE:
01431     case SK_DERIVED:
01432     case SK_EXTERNAL:
01433     case SK_CONST:
01434     case SK_RESULT:
01435       return 0;
01436     case SK_SPECIAL:
01437       return (generic_compare (s1->info->spec, s2->info->spec));
01438     }
01439   BADEXIT;
01440 }
01441 
01442 static bool cref_equal (cref c1, cref c2)
01443 {
01444   return ((c1->lexlevel == c2->lexlevel) &&
01445           (usymId_equal (c1->index, c2->index)));
01446 }
01447 
01448 /*
01449 ** returns true if s1 could be the same storage as s2.
01450 ** i.e., a[?] ~ a[3].  Note its not symmetric ... s1
01451 ** should be more specific.
01452 */
01453 
01454 /*
01455 ** like similar, but matches objects <-> non-objects
01456 */
01457 
01458 static bool 
01459 sRef_uniqueReference (sRef s)
01460 {
01461   return (sRef_isFresh (s) || sRef_isUnique (s) 
01462           || sRef_isOnly (s) || sRef_isStack (s)
01463           || sRef_isAddress (s)); 
01464 }
01465 
01466 static bool
01467 sRef_similarRelaxedAux (sRef s1, sRef s2)
01468 {
01469   if (s1 == s2)
01470     {
01471       if (sRef_isUnknownArrayFetch (s1))
01472         {
01473           return FALSE;
01474         }
01475       else
01476         {
01477           return TRUE;
01478         }
01479     }
01480 
01481   if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
01482 
01483   if (sRef_isConj (s2)) 
01484     return (sRef_similarRelaxedAux (s1, sRef_getConjA (s2)) ||
01485             sRef_similarRelaxedAux (s1, sRef_getConjB (s2)));
01486 
01487   switch (s1->kind)
01488     {
01489     case SK_CVAR:
01490       return ((s2->kind == SK_CVAR)
01491               && (cref_equal (s1->info->cvar, s2->info->cvar)));
01492     case SK_PARAM:
01493       return ((s2->kind == SK_PARAM)
01494               && (s1->info->paramno == s2->info->paramno));
01495     case SK_ARRAYFETCH:
01496       if (s2->kind == SK_ARRAYFETCH)
01497         {
01498           if (sRef_similarRelaxedAux (s1->info->arrayfetch->arr,
01499                                       s2->info->arrayfetch->arr))
01500             {
01501               if (s1->info->arrayfetch->indknown)
01502                 {
01503                   if (s2->info->arrayfetch->indknown)
01504                     {
01505                       return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
01506                     }
01507                   else 
01508                     {
01509                       return FALSE;
01510                     }
01511                 }
01512               else
01513                 {
01514                   return FALSE;
01515                 }
01516             }
01517         }
01518       return FALSE;
01519     case SK_FIELD:
01520       return ((s2->kind == SK_FIELD
01521                && (sRef_similarRelaxedAux (s1->info->field->rec,
01522                                            s2->info->field->rec)
01523                    && cstring_equal (s1->info->field->field,
01524                                      s2->info->field->field))));
01525     case SK_PTR:
01526       return ((s2->kind == SK_PTR)
01527               && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
01528     case SK_ADR:
01529       return ((s2->kind == SK_ADR)
01530               && sRef_similarRelaxedAux (s1->info->ref, s2->info->ref));
01531     case SK_CONJ:
01532       return ((sRef_similarRelaxedAux (s1->info->conj->a, s2) ||
01533               (sRef_similarRelaxedAux (s1->info->conj->b, s2))));
01534     case SK_SPECIAL:
01535       return (s1->info->spec == s2->info->spec);
01536     case SK_UNCONSTRAINED:
01537       return (cstring_equal (s1->info->fname, s2->info->fname));
01538     case SK_DERIVED:
01539     case SK_CONST:
01540     case SK_TYPE:
01541     case SK_NEW:
01542     case SK_UNKNOWN:
01543     case SK_OBJECT:
01544     case SK_EXTERNAL:
01545     case SK_RESULT:
01546       return FALSE;
01547     }
01548   BADEXIT;
01549 }
01550 
01551 bool
01552 sRef_similarRelaxed (sRef s1, sRef s2)
01553 {
01554   bool us1, us2;
01555 
01556   if (s1 == s2) 
01557     {
01558       if (sRef_isThroughArrayFetch (s1))
01559         {
01560           return FALSE;
01561         }
01562       else
01563         {
01564           return TRUE;
01565         }
01566     }
01567 
01568   if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
01569 
01570   us1 = sRef_uniqueReference (s1);
01571   us2 = sRef_uniqueReference (s2);
01572 
01573   if ((s1->kind == SK_EXTERNAL && (s2->kind != SK_EXTERNAL && !us2))
01574       || (s2->kind == SK_EXTERNAL && (s1->kind != SK_EXTERNAL && !us1)))
01575     {
01576       /*
01577       ** Previously, also:
01578       **   || (sRef_isExposed (s1) && !us2) || (sRef_isExposed (s2) && !us1)) ???? 
01579       **
01580       ** No clue why this was there?!
01581       */
01582 
01583 
01584       if (sRef_isExposed (s1) && sRef_isCvar (s1))
01585         {
01586           uentry ue1 = sRef_getUentry (s1);
01587 
01588           if (uentry_isRefParam (ue1))
01589             {
01590               return sRef_similarRelaxedAux (s1, s2);
01591             }
01592         }
01593       
01594       if (sRef_isExposed (s2) && sRef_isCvar (s2))
01595         {
01596           uentry ue2 = sRef_getUentry (s2);
01597 
01598           if (uentry_isRefParam (ue2))
01599             {
01600               return sRef_similarRelaxedAux (s1, s2);
01601             }
01602         }
01603       
01604             return (ctype_match (s1->type, s2->type));
01605     }
01606   else
01607     {
01608             return sRef_similarRelaxedAux (s1, s2);
01609     }
01610 }
01611 
01612 bool
01613 sRef_similar (sRef s1, sRef s2)
01614 {
01615   if (s1 == s2) return TRUE;
01616   if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
01617 
01618   if (sRef_isConj (s2)) 
01619     {
01620       return (sRef_similar (s1, sRef_getConjA (s2)) ||
01621               sRef_similar (s1, sRef_getConjB (s2)));
01622     }
01623 
01624   if (sRef_isDerived (s2))
01625    {
01626      return (sRef_includedBy (s1, s2->info->ref));
01627    }
01628 
01629   switch (s1->kind)
01630     {
01631     case SK_CVAR:
01632       return ((s2->kind == SK_CVAR)
01633               && (cref_equal (s1->info->cvar, s2->info->cvar)));
01634     case SK_PARAM:
01635       return ((s2->kind == SK_PARAM)
01636               && (s1->info->paramno == s2->info->paramno));
01637     case SK_ARRAYFETCH:
01638       if (s2->kind == SK_ARRAYFETCH)
01639         {
01640           if (sRef_similar (s1->info->arrayfetch->arr,
01641                             s2->info->arrayfetch->arr))
01642             {
01643               if (s1->info->arrayfetch->indknown)
01644                 {
01645                   if (s2->info->arrayfetch->indknown)
01646                     {
01647                       return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
01648                     }
01649                   else 
01650                     {
01651                       return TRUE;
01652                     }
01653                 }
01654               else
01655                 {
01656                   return TRUE;
01657                 }
01658             }
01659         }
01660       else 
01661         {
01662           if (s2->kind == SK_PTR)
01663             {
01664               if (sRef_similar (s1->info->arrayfetch->arr,
01665                                 s2->info->ref))
01666                 {
01667                   return TRUE; 
01668                 }
01669             }
01670         }
01671 
01672       return FALSE;
01673     case SK_FIELD:
01674       return ((s2->kind == SK_FIELD
01675                && (sRef_similar (s1->info->field->rec,
01676                                  s2->info->field->rec)
01677                    && cstring_equal (s1->info->field->field,
01678                                      s2->info->field->field))));
01679     case SK_PTR:
01680       if (s2->kind == SK_PTR)
01681         {
01682           return sRef_similar (s1->info->ref, s2->info->ref);
01683         }
01684       else 
01685         {
01686           if (s2->kind == SK_ARRAYFETCH)
01687             {
01688               if (sRef_similar (s2->info->arrayfetch->arr,
01689                                 s1->info->ref))
01690                 {
01691                   return TRUE; 
01692                 }
01693             }
01694         }
01695 
01696       return FALSE;
01697     case SK_ADR:
01698       return ((s2->kind == SK_ADR)
01699               && sRef_similar (s1->info->ref, s2->info->ref));
01700     case SK_CONJ:
01701       return ((sRef_similar (s1->info->conj->a, s2) ||
01702               (sRef_similar (s1->info->conj->b, s2))));
01703     case SK_DERIVED:
01704       return (sRef_includedBy (s2, s1->info->ref));
01705     case SK_UNCONSTRAINED:
01706       return (s2->kind == SK_UNCONSTRAINED
01707               && cstring_equal (s1->info->fname, s2->info->fname));
01708     case SK_CONST:
01709     case SK_TYPE:
01710     case SK_NEW:
01711     case SK_UNKNOWN:
01712     case SK_OBJECT:
01713     case SK_EXTERNAL:
01714     case SK_RESULT:
01715       return FALSE;
01716     case SK_SPECIAL:
01717       return (s2->kind == SK_SPECIAL 
01718               && (s1->info->spec == s2->info->spec));
01719     }
01720 
01721   /*@notreached@*/ DPRINTF (("Fell through for: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
01722   BADEXIT;
01723 }
01724 
01725 /*
01726 ** return TRUE iff small can be derived from big.
01727 **
01728 ** (e.g. x, x.a is includedBy x;
01729 **       x.a is included By x.a;
01730 */
01731 
01732 bool
01733 sRef_includedBy (sRef small, sRef big)
01734 {
01735   if (small == big) return TRUE;
01736   if (sRef_isInvalid (small) || sRef_isInvalid (big)) return FALSE;
01737 
01738   if (sRef_isConj (big)) 
01739     return (sRef_similar (small, sRef_getConjA (big)) ||
01740             sRef_similar (small, sRef_getConjB (big)));
01741 
01742   switch (small->kind)
01743     {
01744     case SK_CVAR:
01745     case SK_PARAM:
01746       return (sRef_same (small, big));
01747     case SK_ARRAYFETCH:
01748       if (big->kind == SK_ARRAYFETCH)
01749         {
01750           if (sRef_same (small->info->arrayfetch->arr, big->info->arrayfetch->arr))
01751             {
01752               if (small->info->arrayfetch->indknown)
01753                 {
01754                   if (big->info->arrayfetch->indknown)
01755                     {
01756                       return (small->info->arrayfetch->ind == big->info->arrayfetch->ind);
01757                     }
01758                   else 
01759                     {
01760                       return TRUE;
01761                     }
01762                 }
01763               else
01764                 {
01765                   return TRUE;
01766                 }
01767             }
01768         }
01769       return (sRef_includedBy (small->info->arrayfetch->arr, big));
01770     case SK_FIELD:
01771       if (big->kind == SK_FIELD)
01772         {
01773           return 
01774             (sRef_same (small->info->field->rec, big->info->field->rec) &&
01775              cstring_equal (small->info->field->field, big->info->field->field));
01776         }
01777       else
01778         {
01779           return (sRef_includedBy (small->info->field->rec, big));
01780         }
01781 
01782     case SK_PTR:
01783       if (big->kind == SK_PTR)
01784         {
01785           return sRef_same (small->info->ref, big->info->ref);
01786         }
01787       else
01788         {
01789           return (sRef_includedBy (small->info->ref, big));
01790         }
01791 
01792     case SK_ADR:
01793       return ((big->kind == SK_ADR) && sRef_similar (small->info->ref, big->info->ref));
01794     case SK_CONJ:
01795       return ((sRef_includedBy (small->info->conj->a, big) ||
01796               (sRef_includedBy (small->info->conj->b, big))));
01797     case SK_DERIVED:
01798       return (sRef_includedBy (small->info->ref, big));
01799     case SK_UNCONSTRAINED:
01800     case SK_CONST:
01801     case SK_TYPE:
01802     case SK_NEW:
01803     case SK_UNKNOWN:
01804     case SK_OBJECT:
01805     case SK_EXTERNAL:
01806     case SK_RESULT:
01807       return FALSE;
01808     case SK_SPECIAL:
01809       switch (small->info->spec)
01810         {
01811         case SR_NOTHING: return TRUE;
01812         case SR_SPECSTATE:
01813         case SR_INTERNAL: return (sRef_isSpecInternalState (big) ||
01814                                   sRef_isFileStatic (big));
01815         case SR_SYSTEM: return (sRef_isSystemState (big));
01816         }
01817     }
01818   BADEXIT;
01819 }
01820 
01821 /*
01822 ** Same is similar to similar, but not quite the same. 
01823 ** same and realSame aren't the same, but they are really similar.
01824 ** similarly, same is the same as same. but realSame is
01825 ** not really the same as same, or similar to similar.
01826 **
01827 ** Similarly to similar, same checks if two sRefs are the same.
01828 ** The similarities end, however, when same compares arrays
01829 ** with unknown indexes.  Similar returns false; same returns true.
01830 **
01831 ** Similarly to similar and same, realSame is the same as same,
01832 ** except they do not behave the same when face with unknown
01833 ** sRefs.  Same thinks they are not the same, but realSame thinks
01834 ** the are.
01835 **
01836 */
01837 
01838 bool
01839 sRef_realSame (sRef s1, sRef s2)
01840 {
01841   if (s1 == s2) return TRUE;  
01842   if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
01843 
01844   switch (s1->kind)
01845     {
01846     case SK_CVAR:
01847       return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
01848     case SK_PARAM:
01849       return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
01850     case SK_ARRAYFETCH:
01851       if (s2->kind == SK_ARRAYFETCH)
01852         {
01853           if (sRef_realSame (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
01854             {
01855               if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
01856                 {
01857                   return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
01858                 }
01859               if (!s1->info->arrayfetch->indknown && !s2->info->arrayfetch->indknown)
01860                 {
01861                   return TRUE;
01862                 }
01863               return FALSE;
01864             }
01865         }
01866       return FALSE;
01867     case SK_FIELD:
01868       return ((s2->kind == SK_FIELD &&
01869                (sRef_realSame (s1->info->field->rec, s2->info->field->rec) &&
01870                 cstring_equal (s1->info->field->field, s2->info->field->field))));
01871     case SK_PTR:
01872       return ((s2->kind == SK_PTR) && sRef_realSame (s1->info->ref, s2->info->ref));
01873     case SK_ADR:
01874       return ((s2->kind == SK_ADR) && sRef_realSame (s1->info->ref, s2->info->ref));
01875     case SK_CONJ:
01876       return ((sRef_realSame (s1->info->conj->a, s2) ||
01877               (sRef_realSame (s1->info->conj->b, s2))));
01878     case SK_OBJECT:
01879       return ((s2->kind == SK_OBJECT) 
01880               && ctype_match (s1->info->object, s2->info->object));
01881     case SK_EXTERNAL:
01882       return ((s2->kind == SK_EXTERNAL) 
01883               && sRef_realSame (s1->info->ref, s2->info->ref));
01884     case SK_SPECIAL:
01885       return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
01886     case SK_DERIVED:
01887       return ((s2->kind == SK_DERIVED) && sRef_realSame (s1->info->ref, s2->info->ref));
01888     case SK_UNCONSTRAINED:
01889       return ((s2->kind == SK_UNCONSTRAINED) 
01890               && (cstring_equal (s1->info->fname, s2->info->fname)));
01891     case SK_TYPE:
01892     case SK_CONST:
01893     case SK_NEW:
01894     case SK_UNKNOWN:
01895     case SK_RESULT:
01896       return TRUE; /* changed this! was false */
01897     }
01898   BADEXIT;
01899 }
01900 
01901 /*
01902 ** same is similar to similar, but not quite the same. 
01903 **
01904 ** Similarly to similar, same checks is two sRefs are the same.
01905 ** The similarities end, however, when same compares arrays
01906 ** with unknown indexes.  Similar returns false; same returns true.
01907 */
01908 
01909 bool
01910 sRef_same (sRef s1, sRef s2)
01911 {
01912   if (s1 == s2) return TRUE;
01913   if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
01914 
01915   switch (s1->kind)
01916     {
01917     case SK_CVAR:
01918       return ((s2->kind == SK_CVAR) && (cref_equal (s1->info->cvar, s2->info->cvar)));
01919     case SK_PARAM:
01920       return ((s2->kind == SK_PARAM) && (s1->info->paramno == s2->info->paramno));
01921     case SK_ARRAYFETCH:
01922       if (s2->kind == SK_ARRAYFETCH)
01923         {
01924           llassert (s1->info->field->rec != s1);
01925           if (sRef_same (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
01926             {
01927               if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
01928                 {
01929                   return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
01930                 }
01931               return TRUE;
01932             }
01933         }
01934       return FALSE;
01935     case SK_FIELD:
01936       {
01937         llassert (s1->info->field->rec != s1);
01938         return ((s2->kind == SK_FIELD &&
01939                  (sRef_same (s1->info->field->rec, s2->info->field->rec) &&
01940                   cstring_equal (s1->info->field->field, s2->info->field->field))));
01941       }
01942     case SK_PTR:
01943       {
01944         llassert (s1->info->ref != s1);
01945         return ((s2->kind == SK_PTR) && sRef_same (s1->info->ref, s2->info->ref));
01946       }
01947     case SK_ADR:
01948       {
01949         llassert (s1->info->ref != s1);
01950         return ((s2->kind == SK_ADR) && sRef_same (s1->info->ref, s2->info->ref));
01951       }
01952     case SK_CONJ:
01953       llassert (s1->info->conj->a != s1);
01954       llassert (s1->info->conj->b != s1);
01955       return ((sRef_same (s1->info->conj->a, s2)) && /* or or and? */
01956               (sRef_same (s1->info->conj->b, s2)));
01957     case SK_SPECIAL:
01958       return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
01959     case SK_DERIVED:
01960       llassert (s1->info->ref != s1);
01961       return ((s2->kind == SK_DERIVED) && sRef_same (s1->info->ref, s2->info->ref));
01962     case SK_CONST:
01963     case SK_UNCONSTRAINED:
01964     case SK_TYPE:
01965     case SK_UNKNOWN:
01966     case SK_NEW:
01967     case SK_OBJECT:
01968     case SK_EXTERNAL:
01969     case SK_RESULT:
01970       return FALSE; 
01971     }
01972   BADEXIT;
01973 }
01974 
01975 /*
01976 ** sort of similar, for use in def/use
01977 */
01978 
01979 static bool
01980 sRef_closeEnough (sRef s1, sRef s2)
01981 {
01982   if (s1 == s2) return TRUE;
01983   if (sRef_isInvalid (s1) || sRef_isInvalid (s2)) return FALSE;
01984 
01985   switch (s1->kind)
01986     {
01987     case SK_CVAR:
01988       return (((s2->kind == SK_CVAR) &&
01989                (cref_equal (s1->info->cvar, s2->info->cvar))) ||
01990               (s2->kind == SK_UNCONSTRAINED && s1->info->cvar->lexlevel == 0));
01991     case SK_UNCONSTRAINED:
01992       return (s2->kind == SK_UNCONSTRAINED
01993               || ((s2->kind == SK_CVAR) && (s2->info->cvar->lexlevel == 0)));
01994     case SK_PARAM:
01995       return ((s2->kind == SK_PARAM) 
01996               && (s1->info->paramno == s2->info->paramno));
01997     case SK_ARRAYFETCH:
01998       if (s2->kind == SK_ARRAYFETCH)
01999         {
02000           if (sRef_closeEnough (s1->info->arrayfetch->arr, s2->info->arrayfetch->arr))
02001             {
02002               if (s1->info->arrayfetch->indknown && s2->info->arrayfetch->indknown)
02003                 {
02004                   return (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind);
02005                 }
02006               return TRUE;
02007             }
02008         }
02009       return FALSE;
02010     case SK_FIELD:
02011       return ((s2->kind == SK_FIELD &&
02012                (sRef_closeEnough (s1->info->field->rec, s2->info->field->rec) &&
02013                 cstring_equal (s1->info->field->field, s2->info->field->field))));
02014     case SK_PTR:
02015       return ((s2->kind == SK_PTR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
02016     case SK_ADR:
02017       return ((s2->kind == SK_ADR) && sRef_closeEnough (s1->info->ref, s2->info->ref));
02018     case SK_DERIVED:
02019       return ((s2->kind == SK_DERIVED) && sRef_closeEnough (s1->info->ref, s2->info->ref));
02020     case SK_CONJ:
02021       return ((sRef_closeEnough (s1->info->conj->a, s2)) ||
02022               (sRef_closeEnough (s1->info->conj->b, s2)));
02023     case SK_SPECIAL:
02024       return ((s2->kind == SK_SPECIAL) && s1->info->spec == s2->info->spec);
02025     case SK_TYPE:
02026     case SK_CONST:
02027     case SK_UNKNOWN:
02028     case SK_NEW:
02029     case SK_OBJECT:
02030     case SK_EXTERNAL:
02031     case SK_RESULT:
02032 
02033       return FALSE;
02034     }
02035   BADEXIT;
02036 }
02037 
02038 /*@exposed@*/ sRef
02039 sRef_fixBaseParam (/*@returned@*/ sRef s, exprNodeList args)
02040 {
02041   if (sRef_isInvalid (s)) return (sRef_undefined);
02042 
02043   switch (s->kind)
02044     {
02045     case SK_UNCONSTRAINED:
02046     case SK_CVAR:
02047       return s;
02048     case SK_PARAM:
02049       {
02050         if (exprNodeList_size (args) > s->info->paramno)
02051           {
02052             exprNode e = exprNodeList_nth (args, s->info->paramno);
02053 
02054             if (exprNode_isError (e))
02055               {
02056                 return sRef_makeUnknown ();
02057               }
02058             
02059             return (exprNode_getSref (e));
02060           }
02061         else
02062           {
02063             return sRef_makeUnknown ();
02064           }
02065       }
02066     case SK_ARRAYFETCH:
02067 
02068       if (s->info->arrayfetch->indknown)
02069         {
02070           return (sRef_makeArrayFetchKnown 
02071                   (sRef_fixBaseParam (s->info->arrayfetch->arr, args),
02072                    s->info->arrayfetch->ind));
02073         }
02074       else
02075         {
02076           return (sRef_makeArrayFetch 
02077                   (sRef_fixBaseParam (s->info->arrayfetch->arr, args)));
02078         }
02079     case SK_FIELD:
02080       return (sRef_makeField (sRef_fixBaseParam (s->info->field->rec, args),
02081                               s->info->field->field));
02082 
02083     case SK_PTR:
02084       return (sRef_makePointer (sRef_fixBaseParam (s->info->ref, args)));
02085 
02086     case SK_ADR:
02087       return (sRef_makeAddress (sRef_fixBaseParam (s->info->ref, args)));
02088 
02089     case SK_CONJ:
02090       return (sRef_makeConj (sRef_fixBaseParam (s->info->conj->a, args),
02091                              sRef_fixBaseParam (s->info->conj->b, args)));
02092     case SK_DERIVED:
02093     case SK_SPECIAL:
02094     case SK_TYPE:
02095     case SK_CONST:
02096     case SK_NEW:
02097     case SK_UNKNOWN:
02098     case SK_OBJECT:
02099     case SK_EXTERNAL:
02100     case SK_RESULT:
02101       return s;
02102     }
02103   BADEXIT;
02104 }
02105 
02106 /*@exposed@*/ sRef
02107 sRef_undumpGlobal (char **c)
02108 {
02109   char p = **c;
02110 
02111   (*c)++;
02112 
02113   switch (p)
02114     {
02115     case 'g':
02116       {
02117         usymId uid = usymId_fromInt (getInt (c));
02118         sstate defstate;
02119         nstate nullstate;
02120         sRef ret;
02121 
02122         checkChar (c, '@');
02123         defstate = sstate_fromInt (getInt (c));
02124 
02125         checkChar (c, '@');
02126         nullstate = nstate_fromInt (getInt (c));
02127 
02128         ret = sRef_makeGlobal (uid, ctype_unknown);
02129         ret->nullstate = nullstate;
02130         ret->defstate = defstate;
02131         return ret;
02132       }
02133     case 's':
02134       {
02135         int i = getInt (c);
02136         speckind sk = speckind_fromInt (i);
02137 
02138         switch (sk)
02139           {
02140           case SR_NOTHING:   return (sRef_makeNothing ());
02141           case SR_INTERNAL:  return (sRef_makeInternalState ());
02142           case SR_SPECSTATE: return (sRef_makeSpecState ());
02143           case SR_SYSTEM:    return (sRef_makeSystemState ());
02144           }
02145         BADEXIT;
02146       }
02147     case '-':
02148       return sRef_undefined;
02149     case 'u':
02150       return sRef_makeUnknown ();
02151     case 'x':
02152       return sRef_makeUnknown ();
02153     default:
02154       llfatalerror (message ("sRef_undumpGlobal: bad line: %s",
02155                              cstring_fromChars (*c)));
02156     }
02157   BADEXIT;
02158 }
02159 
02160 /*@exposed@*/ sRef
02161 sRef_undump (char **c)
02162 {
02163   char p = **c;
02164 
02165   (*c)++;
02166 
02167   switch (p)
02168     {
02169     case 'g':
02170       return (sRef_makeGlobal (usymId_fromInt (getInt (c)), ctype_unknown));
02171     case 'p':
02172       return (sRef_makeParam (getInt (c), ctype_unknown));
02173     case 'r':
02174       return (sRef_makeResultType (ctype_undump (c)));
02175     case 'a':
02176       {
02177         if ((**c >= '0' && **c <= '9') || **c == '-')
02178           {
02179             int i = getInt (c);
02180             sRef arr = sRef_undump (c);
02181             sRef ret = sRef_buildArrayFetchKnown (arr, i);
02182 
02183             return ret;
02184           }
02185         else
02186           {
02187             sRef arr = sRef_undump (c);
02188             sRef ret = sRef_buildArrayFetch (arr);
02189 
02190             return ret;
02191           }
02192       }
02193     case 'f':
02194       {
02195         cstring fname = cstring_undefined;
02196         sRef ret;
02197 
02198         while (**c != '.')
02199           {
02200             fname = cstring_appendChar (fname, **c);
02201             (*c)++;
02202           }
02203         (*c)++;
02204 
02205         ret = sRef_buildField (sRef_undump (c), fname);
02206         cstring_markOwned (fname);
02207         return (ret);
02208       }
02209     case 's':
02210       {
02211         int i = getInt (c);
02212         speckind sk = speckind_fromInt (i);
02213 
02214         switch (sk)
02215           {
02216           case SR_NOTHING:   return (sRef_makeNothing ());
02217           case SR_INTERNAL:  return (sRef_makeInternalState ());
02218           case SR_SPECSTATE: return (sRef_makeSpecState ());
02219           case SR_SYSTEM:    return (sRef_makeSystemState ());
02220           }
02221         BADEXIT;
02222       }
02223     case 't':
02224       {
02225         sRef ptr = sRef_undump (c);
02226         sRef ret = sRef_makePointer (ptr);
02227 
02228         return (ret);
02229       }
02230     case 'd':
02231       {
02232         sRef adr = sRef_undump (c);
02233         sRef ret = sRef_makeAddress (adr);
02234 
02235         return (ret);
02236       }
02237     case 'o':
02238       {
02239         return (sRef_makeObject (ctype_undump (c)));
02240       }
02241     case 'c':
02242       {
02243         sRef s1 = sRef_undump (c);
02244         sRef s2 = ((*c)++, sRef_undump (c));
02245         sRef ret = sRef_makeConj (s1, s2);
02246 
02247         return (ret);
02248       }
02249     case '-':
02250       return sRef_undefined;
02251     case 'u':
02252       return sRef_makeUnknown ();
02253     case 'x':
02254       return sRef_makeUnknown ();
02255     default:
02256       llfatalerror (message ("sRef_undump: bad line: %s", cstring_fromChars (*c)));
02257     }
02258   BADEXIT;
02259 }
02260 
02261 /*@only@*/ cstring
02262 sRef_dump (sRef s)
02263 {
02264   if (sRef_isInvalid (s))
02265     {
02266       return (cstring_makeLiteral ("-"));
02267     }
02268   else
02269     {
02270       switch (s->kind)
02271         {
02272         case SK_PARAM:
02273           return (message ("p%d", s->info->paramno));
02274         case SK_ARRAYFETCH:
02275           if (s->info->arrayfetch->indknown)
02276             {
02277               return (message ("a%d%q", s->info->arrayfetch->ind,
02278                                sRef_dump (s->info->arrayfetch->arr)));
02279             }
02280           else
02281             {
02282               return (message ("a%q", sRef_dump (s->info->arrayfetch->arr)));
02283             }
02284         case SK_FIELD:
02285           return (message ("f%s.%q", s->info->field->field, 
02286                            sRef_dump (s->info->field->rec)));
02287         case SK_PTR:
02288           return (message ("t%q", sRef_dump (s->info->ref)));
02289         case SK_ADR:
02290           return (message ("d%q", sRef_dump (s->info->ref)));
02291         case SK_OBJECT:
02292           return (message ("o%q", ctype_dump (s->info->object)));
02293         case SK_SPECIAL:
02294           return (message ("s%d", (int) s->info->spec));
02295         case SK_CONJ:
02296           return (message ("c%q.%q",
02297                            sRef_dump (s->info->conj->a),
02298                            sRef_dump (s->info->conj->b)));
02299         case SK_CVAR:
02300           if (sRef_isGlobal (s))
02301             {
02302               return (message ("g%d", 
02303                                usymtab_convertId (s->info->cvar->index)));
02304             }
02305           else
02306             {
02307               llcontbug (message ("Dumping local variable: %q",
02308                                   sRef_unparseDebug (s)));
02309               return (cstring_makeLiteral ("u"));
02310             }
02311         case SK_UNKNOWN:
02312           return (cstring_makeLiteral ("u"));
02313         case SK_RESULT:
02314           return (message ("r%q", ctype_dump (s->type)));
02315         case SK_TYPE:
02316         case SK_CONST:
02317         case SK_EXTERNAL:
02318         case SK_DERIVED:
02319         case SK_NEW:
02320         case SK_UNCONSTRAINED:
02321           llcontbug (message ("sRef_dump: bad kind: %q",
02322                               sRef_unparseFull (s)));
02323           return (cstring_makeLiteral ("x"));
02324         }
02325     }
02326      
02327   BADEXIT;
02328 }
02329 
02330 cstring sRef_dumpGlobal (sRef s)
02331 {
02332   if (sRef_isInvalid (s))
02333     {
02334       return (cstring_makeLiteral ("-"));
02335     }
02336   else
02337     {
02338       switch (s->kind)
02339         {
02340         case SK_CVAR:
02341           if (sRef_isGlobal (s))
02342             {
02343               return (message ("g%d@%d@%d", 
02344                                usymtab_convertId (s->info->cvar->index),
02345                                (int) s->defstate,
02346                                (int) s->nullstate));
02347             }
02348           else
02349             {
02350               llcontbug (message ("Dumping local variable: %q",
02351                                   sRef_unparseDebug (s)));
02352               return (cstring_makeLiteral ("u"));
02353             }
02354         case SK_UNKNOWN:
02355           return (cstring_makeLiteral ("u"));
02356         case SK_SPECIAL:
02357           return (message ("s%d", (int) s->info->spec));
02358         default:
02359           llcontbug (message ("sRef_dumpGlobal: bad kind: %q",
02360                               sRef_unparseFull (s)));
02361           return (cstring_makeLiteral ("x"));
02362         }
02363     }
02364      
02365   BADEXIT;
02366 }
02367 
02368 ctype
02369 sRef_deriveType (sRef s, uentryList cl)
02370 {
02371   if (sRef_isInvalid (s)) return ctype_unknown;
02372 
02373   switch (s->kind)
02374     {
02375     case SK_CVAR:
02376       return (uentry_getType (usymtab_getRefQuiet (s->info->cvar->lexlevel, 
02377                                               s->info->cvar->index)));
02378     case SK_UNCONSTRAINED:
02379       return (ctype_unknown);
02380     case SK_PARAM:
02381       return uentry_getType (uentryList_getN (cl, s->info->paramno));
02382     case SK_ARRAYFETCH:
02383       {
02384         ctype ca = sRef_deriveType (s->info->arrayfetch->arr, cl);
02385         
02386         if (ctype_isArray (ca))
02387           {
02388             return (ctype_baseArrayPtr (ca));
02389           }
02390         else if (ctype_isUnknown (ca))
02391           {
02392             return (ca);
02393           }
02394         else
02395           {
02396             llcontbuglit ("sRef_deriveType: inconsistent array type");
02397             return ca;
02398           }
02399       }
02400     case SK_FIELD:
02401       {
02402         ctype ct = sRef_deriveType (s->info->field->rec, cl);
02403         
02404         if (ctype_isStructorUnion (ct))
02405           {
02406             uentry ue = uentryList_lookupField (ctype_getFields (ct), 
02407                                                s->info->field->field);
02408             
02409             if (uentry_isValid (ue))
02410               {
02411                 return (uentry_getType (ue));
02412               }
02413             else
02414               {
02415                 llcontbuglit ("sRef_deriveType: bad field");
02416                 return ctype_unknown;
02417               }
02418           }
02419         else if (ctype_isUnknown (ct))
02420           {
02421             return (ct);
02422           }
02423         else
02424           {
02425             llcontbuglit ("sRef_deriveType: inconsistent field type");
02426             return (ct);
02427           }
02428       }
02429     case SK_PTR:
02430       {
02431         ctype ct = sRef_deriveType (s->info->ref, cl);
02432         
02433         if (ctype_isUnknown (ct)) return ct;
02434         if (ctype_isPointer (ct)) return (ctype_baseArrayPtr (ct));
02435         else
02436           {
02437             llcontbuglit ("sRef_deriveType: inconsistent pointer type");
02438             return (ct);
02439           }
02440       }
02441     case SK_ADR:
02442       {
02443         ctype ct = sRef_deriveType (s->info->ref, cl);
02444         
02445         if (ctype_isUnknown (ct)) return ct;
02446         return ctype_makePointer (ct);
02447       }
02448     case SK_DERIVED:
02449       {
02450         return sRef_deriveType (s->info->ref, cl);
02451       }
02452     case SK_OBJECT:
02453       {
02454         return (s->info->object);
02455       }
02456     case SK_CONJ:
02457       {
02458         return (ctype_makeConj (sRef_deriveType (s->info->conj->a, cl),
02459                                sRef_deriveType (s->info->conj->b, cl)));
02460       }
02461     case SK_RESULT:
02462     case SK_CONST:
02463     case SK_TYPE:
02464       {
02465         return (s->type);
02466       }
02467     case SK_SPECIAL:
02468     case SK_UNKNOWN:
02469     case SK_EXTERNAL:
02470     case SK_NEW:
02471       return ctype_unknown;
02472     }
02473   BADEXIT;
02474 }
02475 
02476 ctype
02477 sRef_getType (sRef s)
02478 {
02479   if (sRef_isInvalid (s)) return ctype_unknown;
02480   return s->type;
02481 }
02482 
02483 
02484 /*@only@*/ cstring
02485 sRef_unparseOpt (sRef s)
02486 {
02487   sRef rb = sRef_getRootBase (s);
02488 
02489   if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
02490     {
02491       cstring ret = sRef_unparse (s);
02492       
02493       llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
02494 
02495       if (!cstring_isEmpty (ret))
02496         {
02497           return (cstring_appendChar (ret, ' '));
02498         }
02499       else
02500         {
02501           return ret;
02502         }
02503     }
02504 
02505   return cstring_undefined;
02506 }
02507 
02508 cstring
02509 sRef_unparsePreOpt (sRef s)
02510 {
02511   sRef rb = sRef_getRootBase (s);
02512 
02513   if (sRef_isMeaningful (rb) && !sRef_isConst (rb))
02514     {
02515       cstring ret = sRef_unparse (s);
02516       
02517       llassertprint (!cstring_equalLit (ret, "?"), ("print: %s", sRef_unparseDebug (s)));
02518       return (cstring_prependCharO (' ', ret));
02519     }
02520 
02521   return cstring_undefined;
02522 }
02523 
02524 /*@only@*/ cstring
02525 sRef_unparse (sRef s)
02526 {
02527   if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
02528 
02529   if (context_inFunctionLike ())
02530     {
02531       return (sRef_unparseWithArgs (s, context_getParams ()));
02532     }
02533   else
02534     {
02535       return (sRef_unparseNoArgs (s));
02536     }
02537 }
02538 
02539 static /*@only@*/ cstring
02540 sRef_unparseWithArgs (sRef s, uentryList args)
02541 {
02542   if (sRef_isInvalid (s))
02543     {
02544       return (cstring_makeLiteral ("?"));
02545     }
02546 
02547   switch (s->kind)
02548     {
02549     case SK_CVAR:
02550       return (uentry_getName (usymtab_getRefQuiet (s->info->cvar->lexlevel,
02551                                                    s->info->cvar->index)));
02552     case SK_UNCONSTRAINED:
02553       return (cstring_copy (s->info->fname));
02554     case SK_PARAM:
02555       {
02556         if (s->info->paramno < uentryList_size (args))
02557           {
02558             uentry ue = uentryList_getN (args, s->info->paramno);
02559             
02560             if (uentry_isValid (ue))
02561               return uentry_getName (ue);
02562           }
02563 
02564         return (message ("<bad param: %q / args %q",
02565                          sRef_unparseDebug (s),
02566                          uentryList_unparse (args)));
02567       }
02568     case SK_ARRAYFETCH:
02569       if (s->info->arrayfetch->indknown)
02570         {
02571           return (message ("%q[%d]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args),
02572                                 s->info->arrayfetch->ind));
02573         }
02574       else
02575         {
02576           return (message ("%q[]", sRef_unparseWithArgs (s->info->arrayfetch->arr, args)));
02577         }
02578     case SK_FIELD:
02579       if (s->info->field->rec->kind == SK_PTR)
02580         {
02581           sRef ptr = s->info->field->rec;
02582 
02583           return (message ("%q->%s", sRef_unparseWithArgs (ptr->info->ref, args),
02584                            s->info->field->field));       
02585         }
02586       return (message ("%q.%s", sRef_unparseWithArgs (s->info->field->rec, args),
02587                        s->info->field->field));
02588 
02589     case SK_PTR:
02590       {
02591         sRef ref = sRef_fixConj (s->info->ref);
02592         skind sk = ref->kind;
02593         cstring ret;
02594 
02595         if (sk == SK_NEW)
02596           {
02597             ret = message ("storage pointed to by %q",
02598                            sRef_unparseWithArgs (ref, args));
02599           }
02600         else if (skind_isSimple (sk) || sk == SK_PTR)
02601           {
02602             ret = message ("*%q", sRef_unparseWithArgs (ref, args));
02603           }
02604         else
02605           {
02606             ret = message ("*(%q)", sRef_unparseWithArgs (ref, args));
02607           }
02608 
02609         return ret;
02610       }
02611     case SK_ADR:
02612       return (message ("&%q", sRef_unparseWithArgs (s->info->ref, args)));
02613     case SK_OBJECT:
02614       return (cstring_copy (ctype_unparse (s->info->object)));
02615     case SK_CONJ:
02616       return (sRef_unparseWithArgs (sRef_getConjA (s), args));
02617     case SK_NEW:
02618       if (cstring_isDefined (s->info->fname))
02619         {
02620           return (message ("[result of %s]", s->info->fname));
02621         }
02622       else
02623         {
02624           return (cstring_makeLiteral ("<new>"));
02625         }
02626     case SK_UNKNOWN:
02627       return (cstring_makeLiteral ("?"));
02628     case SK_DERIVED:
02629       return (message ("<derived %q>", sRef_unparse (s->info->ref)));
02630     case SK_EXTERNAL:
02631       return (message ("<external %q>", sRef_unparse (s->info->ref)));
02632     case SK_TYPE:
02633       return (message ("<type %s>", ctype_unparse (s->type)));
02634     case SK_CONST:
02635       return (message ("<const %s>", ctype_unparse (s->type)));
02636     case SK_SPECIAL:
02637       return (cstring_makeLiteral
02638               (s->info->spec == SR_NOTHING ? "nothing"
02639                : s->info->spec == SR_INTERNAL ? "internal state"
02640                : s->info->spec == SR_SPECSTATE ? "spec state"
02641                : s->info->spec == SR_SYSTEM ? "file system state"
02642                : "<spec error>"));
02643     case SK_RESULT:
02644       return cstring_makeLiteral ("result");
02645     default:
02646       {
02647         llbug (message ("Bad sref, kind = %d", (int) s->kind));
02648       }
02649     }
02650 
02651   BADEXIT;
02652 }
02653 
02654 /*@only@*/ cstring
02655 sRef_unparseDebug (sRef s)
02656 {
02657   if (sRef_isInvalid (s)) return (cstring_makeLiteral ("<undef>"));
02658 
02659   switch (s->kind)
02660     {
02661     case SK_UNCONSTRAINED:
02662       return (message ("<unconstrained %s>", s->info->fname));
02663     case SK_CVAR:
02664       {
02665         uentry ce;
02666 
02667         ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, s->info->cvar->index);
02668 
02669         if (uentry_isInvalid (ce))
02670           {
02671             return (message ("<scope: %d.%d *invalid*>", 
02672                              s->info->cvar->lexlevel,
02673                              s->info->cvar->index));
02674           }
02675         else
02676           {
02677             return (message ("<scope: %d.%d *%q*>", 
02678                              s->info->cvar->lexlevel,
02679                              s->info->cvar->index,
02680                              uentry_getName (ce)));
02681           }
02682 
02683       }
02684     case SK_PARAM:
02685       {
02686         return (message ("<parameter %d>", s->info->paramno + 1));
02687       }
02688     case SK_ARRAYFETCH:
02689       if (s->info->arrayfetch->indknown)
02690         {
02691           return (message ("%q[%d]", sRef_unparseDebug (s->info->arrayfetch->arr),
02692                            s->info->arrayfetch->ind));
02693         }
02694       else
02695         {
02696           return (message ("%q[]", sRef_unparseDebug (s->info->arrayfetch->arr)));
02697         }
02698     case SK_FIELD:
02699       return (message ("%q.%s", sRef_unparseDebug (s->info->field->rec),
02700                        s->info->field->field));
02701     case SK_PTR:
02702       return (message ("*(%q)", sRef_unparseDebug (s->info->ref)));
02703     case SK_ADR:
02704       return (message ("&%q", sRef_unparseDebug (s->info->ref)));
02705     case SK_OBJECT:
02706       return (message ("<object type %s>", ctype_unparse (s->info->object)));
02707     case SK_CONJ:
02708       return (message ("%q | %q", sRef_unparseDebug (s->info->conj->a),
02709                        sRef_unparseDebug (s->info->conj->b)));
02710     case SK_NEW:
02711       return message ("<new: %s>", s->info->fname);
02712     case SK_DERIVED:
02713       return (message ("<derived %q>", sRef_unparseDebug (s->info->ref)));
02714     case SK_EXTERNAL:
02715       return (message ("<external %q>", sRef_unparseDebug (s->info->ref)));
02716     case SK_TYPE:
02717       return (message ("<type %s>", ctype_unparse (s->type)));
02718     case SK_CONST:
02719       return (message ("<const %s>", ctype_unparse (s->type)));
02720     case SK_RESULT:
02721       return (message ("<result %s>", ctype_unparse (s->type)));
02722     case SK_SPECIAL:
02723       return (message ("<spec %s>",
02724                        cstring_makeLiteralTemp
02725                        (s->info->spec == SR_NOTHING ? "nothing"
02726                         : s->info->spec == SR_INTERNAL ? "internalState"
02727                         : s->info->spec == SR_SPECSTATE ? "spec state"
02728                         : s->info->spec == SR_SYSTEM ? "fileSystem"
02729                         : "error")));
02730     case SK_UNKNOWN:
02731       return cstring_makeLiteral ("<unknown>");
02732     }
02733 
02734   BADEXIT;
02735 }
02736 
02737 static /*@only@*/ cstring
02738 sRef_unparseNoArgs (sRef s)
02739 {
02740   if (sRef_isInvalid (s)) return (cstring_makeLiteral ("?"));
02741 
02742   switch (s->kind)
02743     {
02744     case SK_UNCONSTRAINED:
02745       return (cstring_copy (s->info->fname));
02746     case SK_CVAR:
02747       {
02748         uentry ce = usymtab_getRefQuiet (s->info->cvar->lexlevel, 
02749                                          s->info->cvar->index);
02750 
02751         if (uentry_isInvalid (ce))
02752           {
02753             llcontbug (message ("sRef_unparseNoArgs: bad cvar: %q", sRef_unparseDebug (s)));
02754             return (sRef_unparseDebug (s)); 
02755           }
02756         else
02757           {
02758             return (uentry_getName (ce));
02759           }
02760       }
02761     case SK_ARRAYFETCH:
02762       if (s->info->arrayfetch->indknown)
02763         {
02764           return (message ("%q[%d]", sRef_unparseNoArgs (s->info->arrayfetch->arr),
02765                            s->info->arrayfetch->ind));
02766         }
02767       else
02768         {
02769           return (message ("%q[]", sRef_unparseNoArgs (s->info->arrayfetch->arr)));
02770         }
02771     case SK_FIELD:
02772       return (message ("%q.%s", sRef_unparseNoArgs (s->info->field->rec),
02773                        s->info->field->field));
02774     case SK_PTR:
02775       {
02776         sRef ref = sRef_fixConj (s->info->ref);
02777         skind sk = ref->kind;
02778         cstring ret;
02779 
02780         if (skind_isSimple (sk) || sk == SK_PTR)
02781           {
02782             ret = message ("*%q", sRef_unparseNoArgs (ref));
02783           }
02784         else
02785           {
02786             ret = message ("*(%q)", sRef_unparseNoArgs (ref));
02787           }
02788 
02789         return (ret);
02790       }
02791     case SK_ADR:
02792       return (message ("&%q", sRef_unparseNoArgs (s->info->ref)));
02793     case SK_OBJECT:
02794       return (cstring_copy (ctype_unparse (s->info->object)));
02795     case SK_CONJ:
02796       return (sRef_unparseNoArgs (s->info->conj->a));
02797     case SK_NEW:
02798       return (message ("result of %s", s->info->fname));
02799     case SK_DERIVED:
02800       return (message ("<der %q>", sRef_unparseNoArgs (s->info->ref)));
02801     case SK_EXTERNAL:
02802       return message ("<ext %q>", sRef_unparseNoArgs (s->info->ref));
02803     case SK_SPECIAL:
02804       return (cstring_makeLiteral
02805               (s->info->spec == SR_NOTHING ? "nothing"
02806                : s->info->spec == SR_INTERNAL ? "internal state"
02807                : s->info->spec == SR_SPECSTATE ? "spec state"
02808                : s->info->spec == SR_SYSTEM ? "file system state"
02809                : "<spec error>"));
02810     case SK_RESULT:
02811       return cstring_makeLiteral ("result");
02812     case SK_CONST:
02813     case SK_TYPE:
02814     case SK_UNKNOWN:
02815       return cstring_makeLiteral ("?");
02816     case SK_PARAM:
02817       /* llcontbug (message ("sRef_unparseNoArgs: bad case: %q", sRef_unparseDebug (s))); */
02818       return (sRef_unparseDebug (s));
02819     }
02820   BADEXIT;
02821 }
02822 
02823 /*@dependent@*/ sRef sRef_makeUnconstrained (cstring fname)
02824 {
02825   sRef s = sRef_new ();
02826 
02827   s->kind = SK_UNCONSTRAINED;
02828   s->info = (sinfo) dmalloc (sizeof (*s->info));
02829   s->info->fname = fname;
02830 
02831   return (s);
02832 }
02833 
02834 cstring sRef_unconstrainedName (sRef s)
02835 {
02836   llassert (sRef_isUnconstrained (s));
02837 
02838   return s->info->fname;
02839 }
02840 
02841 bool sRef_isUnconstrained (sRef s) 
02842 {
02843   return (sRef_isValid(s) && s->kind == SK_UNCONSTRAINED);
02844 }
02845 
02846 static /*@dependent@*/ /*@notnull@*/ sRef 
02847   sRef_makeCvarAux (int level, usymId index, ctype ct)
02848 {
02849   sRef s = sRef_new ();
02850 
02851     s->kind = SK_CVAR;
02852   s->info = (sinfo) dmalloc (sizeof (*s->info));
02853 
02854   s->info->cvar = (cref) dmalloc (sizeof (*s->info->cvar));
02855   s->info->cvar->lexlevel = level;
02856   s->info->cvar->index = index;
02857 
02858   /* for now, all globals are defined; all locals, aren't */
02859 
02860   if (level <= fileScope)
02861     {
02862       s->defstate = SS_UNKNOWN;
02863     }
02864   else 
02865     {
02866       ctype rct = ctype_realType (ct);
02867 
02868       if (level != paramsScope
02869           && (ctype_isStructorUnion (rct) || ctype_isRealArray (rct)))
02870         {
02871           s->defstate = SS_ALLOCATED; 
02872           s->oaliaskind = s->aliaskind = AK_STACK;
02873         }
02874       else
02875         {
02876           s->defstate = SS_UNDEFINED;
02877           s->oaliaskind = s->aliaskind = AK_LOCAL;
02878         }
02879     }
02880 
02881   s->type = ct;
02882 
02883   llassert (level >= globScope);
02884   llassert (usymId_isValid (index));
02885 
02886   return s;
02887 }
02888 
02889 /*@dependent@*/ sRef sRef_makeCvar (int level, usymId index, ctype ct)
02890 {
02891   return (sRef_makeCvarAux (level, index, ct));
02892 }
02893 
02894 int sRef_lexLevel (sRef s)
02895 {
02896   if (sRef_isValid (s))
02897     {
02898       sRef conj;
02899 
02900       conj = sRef_fixConj (s);
02901       s = sRef_getRootBase (conj);
02902       
02903       if (sRef_isValid (s) && s->kind == SK_CVAR)
02904         {
02905           return (s->info->cvar->lexlevel);
02906         }
02907     }
02908 
02909   return globScope;
02910 }
02911 
02912 sRef
02913 sRef_makeGlobal (usymId l, ctype ct)
02914 {
02915   return (sRef_makeCvar (globScope, l, ct));
02916 }
02917 
02918 void
02919 sRef_setParamNo (sRef s, int l)
02920 {
02921   llassert (sRef_isValid (s) && s->kind == SK_PARAM);
02922   s->info->paramno = l;
02923 }
02924 
02925 /*@dependent@*/ sRef
02926 sRef_makeParam (int l, ctype ct)
02927 {
02928   sRef s = sRef_new ();
02929 
02930   s->kind = SK_PARAM;
02931   s->type = ct;
02932 
02933   s->info = (sinfo) dmalloc (sizeof (*s->info));
02934   s->info->paramno = l; 
02935   s->defstate = SS_UNKNOWN; /* (probably defined, unless its an out parameter) */
02936 
02937   return s;
02938 }
02939 
02940 bool
02941 sRef_isIndexKnown (sRef arr)
02942 {
02943   bool res;
02944 
02945   llassert (sRef_isValid (arr));
02946   arr = sRef_fixConj (arr);
02947   
02948   llassert (arr->kind == SK_ARRAYFETCH);  
02949   res = arr->info->arrayfetch->indknown;
02950   return (res);
02951 }
02952 
02953 int
02954 sRef_getIndex (sRef arr)
02955 {
02956   int result;
02957 
02958   llassert (sRef_isValid (arr));
02959   arr = sRef_fixConj (arr);
02960 
02961   llassert (arr->kind == SK_ARRAYFETCH);  
02962 
02963   if (!arr->info->arrayfetch->indknown)
02964     {
02965       llcontbug (message ("sRef_getIndex: unknown: %q", sRef_unparse (arr)));
02966       result = 0; 
02967     }
02968   else
02969     {
02970       result = arr->info->arrayfetch->ind;
02971     }
02972 
02973   return result;
02974 }
02975 
02976 static bool sRef_isZerothArrayFetch (/*@notnull@*/ sRef s)
02977 {
02978   return (s->kind == SK_ARRAYFETCH
02979           && s->info->arrayfetch->indknown
02980           && (s->info->arrayfetch->ind == 0));
02981 }
02982 
02983 /*@exposed@*/ sRef sRef_makeAddress (/*@exposed@*/ sRef t)
02984 {
02985   
02986   if (sRef_isInvalid (t)) return sRef_undefined;
02987 
02988   if (sRef_isPointer (t))
02989     {
02990       return (t->info->ref);
02991     }
02992   else if (sRef_isZerothArrayFetch (t))
02993     {
02994       return (t->info->arrayfetch->arr);
02995     }
02996   else
02997     {
02998       sRef s = sRef_new ();
02999       
03000       s->kind = SK_ADR;
03001       s->type = ctype_makePointer (t->type);
03002       s->info = (sinfo) dmalloc (sizeof (*s->info));
03003       s->info->ref = t;
03004       
03005       if (t->defstate == SS_UNDEFINED) 
03006         /* no! it is allocated even still: && !ctype_isPointer (t->type)) */
03007         {
03008           s->defstate = SS_ALLOCATED;
03009         }
03010       else
03011         {
03012           s->defstate = t->defstate;
03013         }
03014 
03015       if (t->aliaskind == AK_LOCAL)
03016         {
03017           if (sRef_isLocalVar (t))
03018             {
03019               s->aliaskind = AK_STACK;
03020             }
03021         }
03022 
03023       return s;
03024     }
03025 }
03026 
03027 cstring sRef_getField (sRef s)
03028 {
03029   cstring res;
03030 
03031   llassert (sRef_isValid (s));
03032   s = sRef_fixConj (s);
03033 
03034   llassertprint (sRef_isValid (s) && (s->kind == SK_FIELD),
03035                  ("s = %s", sRef_unparseDebug (s)));
03036 
03037   res = s->info->field->field;
03038   return (res);
03039 }
03040 
03041 sRef sRef_getBase (sRef s)
03042 {
03043   sRef res;
03044 
03045   if (sRef_isInvalid (s)) return (sRef_undefined);
03046 
03047   s = sRef_fixConj (s);
03048 
03049   switch (s->kind)
03050     {
03051     case SK_ADR:
03052     case SK_PTR:
03053     case SK_DERIVED:
03054     case SK_EXTERNAL:
03055       res = s->info->ref;
03056       break;
03057     case SK_FIELD:
03058       res = s->info->field->rec;
03059       break;
03060 
03061     case SK_ARRAYFETCH:
03062       res = s->info->arrayfetch->arr;
03063       break;
03064 
03065     default:
03066       res = sRef_undefined; /* shouldn't need it */
03067     }
03068 
03069   return (res);
03070 }
03071 
03072 /*
03073 ** same as getBase, except returns invalid
03074 ** (and doesn't use adr's)                   
03075 */
03076 
03077 sRef
03078 sRef_getBaseSafe (sRef s)
03079 {
03080   sRef res;
03081 
03082   if (sRef_isInvalid (s)) { return sRef_undefined; }
03083 
03084   s = sRef_fixConj (s);
03085 
03086   switch (s->kind)
03087     {
03088     case SK_PTR:
03089             res = s->info->ref; 
03090       break;
03091     case SK_FIELD:
03092             res = s->info->field->rec; break;
03093     case SK_ARRAYFETCH:
03094             res = s->info->arrayfetch->arr; 
03095       break;
03096     default:
03097       res = sRef_undefined; break;
03098     }
03099 
03100   return res;
03101 }
03102 
03103 /*@constant int MAXBASEDEPTH;@*/
03104 # define MAXBASEDEPTH 25
03105 
03106 static /*@exposed@*/ sRef 
03107 sRef_getRootBaseAux (sRef s, int depth)
03108 {
03109   if (sRef_isInvalid (s)) return sRef_undefined;
03110 
03111   if (depth > MAXBASEDEPTH)
03112     {
03113       llgenmsg (message 
03114                 ("Warning: reference base limit exceeded for %q. "
03115                  "This either means there is a variable with at least "
03116                  "%d indirections from this reference, or "
03117                  "there is a bug in LCLint.",
03118                  sRef_unparse (s),
03119                  MAXBASEDEPTH),
03120                 g_currentloc);
03121 
03122       return sRef_undefined;
03123     }
03124 
03125   switch (s->kind)
03126     {
03127     case SK_ADR:
03128     case SK_PTR:
03129       return (sRef_getRootBaseAux (s->info->ref, depth + 1));
03130     case SK_FIELD:
03131       return (sRef_getRootBaseAux (s->info->field->rec, depth + 1));
03132     case SK_ARRAYFETCH:
03133       return (sRef_getRootBaseAux (s->info->arrayfetch->arr, depth + 1));
03134     case SK_CONJ:
03135       return (sRef_getRootBaseAux (sRef_fixConj (s), depth + 1));
03136     default:
03137       return s;
03138     }
03139 }
03140 
03141 sRef sRef_getRootBase (sRef s)
03142 {
03143   return (sRef_getRootBaseAux (s, 0));
03144 }
03145 
03146 static bool sRef_isDeep (sRef s)
03147 {
03148   if (sRef_isInvalid (s)) return FALSE;
03149   
03150   switch (s->kind)
03151     {
03152     case SK_ADR:
03153     case SK_PTR:
03154     case SK_FIELD:
03155     case SK_ARRAYFETCH:
03156       return TRUE;
03157     case SK_CONJ:
03158       return (sRef_isDeep (sRef_fixConj (s)));
03159     default:
03160       return FALSE;
03161     }
03162 }
03163 
03164 static int sRef_depth (sRef s)
03165 {
03166   if (sRef_isInvalid (s)) return 0;
03167   
03168   switch (s->kind)
03169     {
03170     case SK_ADR:
03171     case SK_PTR:
03172     case SK_DERIVED:
03173     case SK_EXTERNAL:
03174       return 1 + sRef_depth (s->info->ref);
03175     case SK_FIELD:
03176       return 1 + sRef_depth (s->info->field->rec);
03177     case SK_ARRAYFETCH:
03178       return 1 + sRef_depth (s->info->arrayfetch->arr);
03179     case SK_CONJ:
03180       return (sRef_depth (sRef_fixConj (s)));
03181     default:
03182       return 1;
03183     }
03184 }
03185 
03186 sRef
03187 sRef_makeObject (ctype o)
03188 {
03189   sRef s = sRef_new ();
03190 
03191   s->kind = SK_OBJECT;
03192   s->info = (sinfo) dmalloc (sizeof (*s->info));
03193   s->info->object = o;
03194   return s;
03195 }
03196 
03197 sRef sRef_makeExternal (/*@exposed@*/ sRef t)
03198 {
03199   sRef s = sRef_new ();
03200 
03201   llassert (sRef_isValid (t));
03202 
03203   s->kind = SK_EXTERNAL;
03204   s->info = (sinfo) dmalloc (sizeof (*s->info));
03205   s->type = t->type;
03206   s->info->ref = t;
03207   return s;
03208 }
03209 
03210 sRef sRef_makeDerived (/*@exposed@*/ sRef t)
03211 {
03212   if (sRef_isValid (t))
03213     {
03214       sRef s = sRef_new ();
03215       
03216       s->kind = SK_DERIVED;
03217       s->info = (sinfo) dmalloc (sizeof (*s->info));
03218       s->info->ref = t;
03219       
03220       s->type = t->type;
03221       return s;
03222     }
03223   else
03224     {
03225       return sRef_undefined;
03226     }
03227 }
03228 
03229 /*
03230 ** definitely NOT symmetric:
03231 **
03232 **   res fills in unknown state information from other
03233 */
03234 
03235 void
03236 sRef_mergeStateQuiet (sRef res, sRef other)
03237 {
03238   llassert (sRef_isValid (res));
03239   llassert (sRef_isValid (other));
03240 
03241   res->modified = res->modified || other->modified;
03242   res->safe = res->safe && other->safe;
03243 
03244   if (res->defstate == SS_UNKNOWN) 
03245     {
03246       res->defstate = other->defstate;
03247       res->definfo = alinfo_update (res->definfo, other->definfo);
03248     }
03249 
03250   if (res->aliaskind == AK_UNKNOWN || 
03251       (res->aliaskind == AK_LOCAL && alkind_isKnown (other->aliaskind)))
03252     {
03253       res->aliaskind = other->aliaskind;
03254       res->oaliaskind = other->oaliaskind;
03255       res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
03256     }
03257 
03258   if (res->expkind == XO_UNKNOWN)
03259     {
03260       res->expkind = other->expkind;
03261       res->oexpkind = other->oexpkind;
03262       res->expinfo = alinfo_update (res->expinfo, other->expinfo);
03263     }
03264   
03265   /* out takes precedence over implicitly defined */
03266   if (res->defstate == SS_DEFINED && other->defstate != SS_UNKNOWN) 
03267     {
03268       res->defstate = other->defstate;
03269       res->definfo = alinfo_update (res->definfo, other->definfo);
03270     }
03271 
03272   if (other->nullstate == NS_ERROR || res->nullstate == NS_ERROR) 
03273     {
03274       res->nullstate = NS_ERROR;
03275     }
03276   else
03277     {
03278       if (other->nullstate != NS_UNKNOWN 
03279           && (res->nullstate == NS_UNKNOWN || res->nullstate == NS_NOTNULL 
03280               || res->nullstate == NS_MNOTNULL))
03281         {
03282           res->nullstate = other->nullstate;
03283           res->nullinfo = alinfo_update (res->nullinfo, other->nullinfo);
03284         }
03285     }
03286 }
03287 
03288 /*
03289 ** definitely NOT symmetric:
03290 **
03291 **   res fills in known state information from other
03292 */
03293 
03294 void
03295 sRef_mergeStateQuietReverse (sRef res, sRef other)
03296 {
03297   bool changed = FALSE;
03298 
03299   llassert (sRef_isValid (res));
03300   llassert (sRef_isValid (other));
03301 
03302   if (res->kind != other->kind)
03303     {
03304       changed = TRUE;
03305 
03306       sinfo_free (res);
03307 
03308       res->kind = other->kind;
03309       res->type = other->type;
03310       res->info = sinfo_fullCopy (other);
03311     }
03312   else
03313     {
03314       if (!ctype_equal (res->type, other->type))
03315         {
03316           changed = TRUE;
03317           res->type = other->type;
03318         }
03319       
03320       sinfo_update (res, other);
03321     }
03322 
03323   res->modified = res->modified || other->modified;
03324   res->safe = res->safe && other->safe;
03325 
03326   if (res->aliaskind != other->aliaskind
03327       && (res->aliaskind == AK_UNKNOWN
03328           || ((res->aliaskind == AK_LOCAL 
03329                || (res->aliaskind == AK_REFCOUNTED
03330                    && other->aliaskind != AK_LOCAL))
03331               && other->aliaskind != AK_UNKNOWN)))
03332     {
03333       changed = TRUE;
03334       res->aliaskind = other->aliaskind;
03335       res->oaliaskind = other->oaliaskind;
03336       res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
03337           }
03338 
03339   if (other->expkind != XO_UNKNOWN && other->expkind != res->expkind)
03340     {
03341       changed = TRUE;
03342       res->expkind = other->expkind;
03343       res->expinfo = alinfo_update (res->expinfo, other->expinfo);
03344     }
03345 
03346   if (other->oexpkind != XO_UNKNOWN)
03347     {
03348       res->oexpkind = other->oexpkind;
03349     }
03350 
03351   /* out takes precedence over implicitly defined */
03352 
03353   if (res->defstate != other->defstate)
03354     {
03355       if (other->defstate != SS_UNKNOWN)
03356         {
03357           res->defstate = other->defstate;
03358         }
03359     }
03360 
03361   if (other->nullstate == NS_ERROR || res->nullstate == NS_ERROR)
03362     {
03363       if (res->nullstate != NS_ERROR)
03364         {
03365           res->nullstate = NS_ERROR;
03366           changed = TRUE;
03367         }
03368     }
03369   else
03370     {
03371       if (other->nullstate != NS_UNKNOWN && other->nullstate != res->nullstate)
03372         {
03373           changed = TRUE;
03374           res->nullstate = other->nullstate;
03375           res->nullinfo = alinfo_update (res->nullinfo, other->nullinfo);
03376         }
03377     }
03378 
03379   if (changed)
03380     {
03381       sRef_clearDerived (res); 
03382     }
03383 }
03384 
03385 void 
03386 sRef_mergeState (sRef res, sRef other, clause cl, fileloc loc)
03387 {
03388   if (sRef_isValid (res) && sRef_isValid (other))
03389     {
03390       sRef_mergeStateAux (res, other, cl, FALSE, loc, TRUE);
03391     }
03392   else
03393     {
03394       if (sRef_isInvalid (res))
03395         {
03396           llbug (message ("sRef_mergeState: invalid res sRef: %q", 
03397                           sRef_unparseDebug (other)));
03398         }
03399       else 
03400         {
03401           llbug (message ("sRef_mergeState: invalid other sRef: %q", 
03402                           sRef_unparseDebug (res)));
03403         }
03404     }
03405 }
03406 
03407 void 
03408 sRef_mergeOptState (sRef res, sRef other, clause cl, fileloc loc)
03409 {
03410   if (sRef_isValid (res) && sRef_isValid (other))
03411     {
03412       sRef_mergeStateAux (res, other, cl, TRUE, loc, TRUE);
03413     }
03414   else
03415     {
03416       if (sRef_isInvalid (res))
03417         {
03418           llbug (message ("sRef_mergeOptState: invalid res sRef: %q", 
03419                           sRef_unparseDebug (other)));
03420         }
03421       else 
03422         {
03423           llbug (message ("sRef_mergeOptState: invalid other sRef: %q", 
03424                           sRef_unparseDebug (res)));
03425         }
03426     }
03427 }
03428 
03429 static void
03430 sRef_mergeStateAux (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other, 
03431                     clause cl, bool opt, fileloc loc,
03432                     bool doDerivs)
03433    /*@modifies res@*/ 
03434 {
03435   llassertfatal (sRef_isValid (res));
03436   llassertfatal (sRef_isValid (other));
03437   
03438   res->modified = res->modified || other->modified;
03439 
03440   if (res->kind == other->kind 
03441       || (other->kind == SK_UNKNOWN || res->kind == SK_UNKNOWN))
03442     {
03443       sstate odef = other->defstate;
03444       sstate rdef = res->defstate;
03445       nstate onull = other->nullstate;
03446       
03447       /*
03448       ** yucky stuff to handle 
03449       **
03450       **   if (s) free (s);
03451       */
03452 
03453       if (other->defstate == SS_DEAD 
03454           && ((sRef_isOnly (res) && sRef_definitelyNull (res))
03455               || (res->defstate == SS_UNDEFINED
03456                   || res->defstate == SS_UNUSEABLE)))
03457         {
03458           if (res->defstate == SS_UNDEFINED
03459               || res->defstate == SS_UNUSEABLE)
03460             {
03461               res->defstate = SS_UNUSEABLE;
03462             }
03463           else
03464             {
03465               res->defstate = SS_DEAD;
03466             }
03467 
03468           res->definfo = alinfo_update (res->definfo, other->definfo);
03469           sRef_clearDerived (other);
03470           sRef_clearDerived (res);
03471         }
03472       else if (res->defstate == SS_DEAD 
03473                && ((sRef_isOnly (other) && sRef_definitelyNull (other))
03474                    || (other->defstate == SS_UNDEFINED
03475                        || other->defstate == SS_UNUSEABLE)))
03476         {
03477           if (other->defstate == SS_UNDEFINED
03478               || other->defstate == SS_UNUSEABLE)
03479             {
03480               res->defstate = SS_UNUSEABLE;
03481             }
03482           else
03483             {
03484               res->defstate = SS_DEAD;
03485             }
03486           
03487           sRef_clearDerived (other);
03488           sRef_clearDerived (res);
03489         }
03490       else if (res->defstate == SS_DEFINED 
03491                && (other->defstate == SS_ALLOCATED 
03492                    && sRef_definitelyNull (other)))
03493         {
03494           other->defstate = SS_DEFINED; /* definitely null! */
03495         }
03496       else if (other->defstate == SS_DEFINED
03497                && (res->defstate == SS_ALLOCATED && sRef_definitelyNull (res)))
03498         {
03499           res->defstate = SS_DEFINED;
03500           res->definfo = alinfo_update (res->definfo, other->definfo);
03501         }
03502       else
03503         {
03504           ; /* okay */
03505         }
03506 
03507       if (res->defstate == SS_DEAD && other->defstate == SS_DEAD)
03508         {
03509           sRef_clearDerived (other);
03510           sRef_clearDerived (res);
03511         }
03512 
03513       /*
03514       ** only & dead isn't really an only!
03515       */
03516 
03517       if (alkind_isOnly (other->aliaskind) && other->defstate == SS_DEAD)
03518         {
03519           other->aliaskind = AK_UNKNOWN;
03520         }
03521 
03522       if (alkind_isOnly (res->aliaskind) && res->defstate == SS_DEAD)
03523         {
03524           res->aliaskind = AK_UNKNOWN;
03525         }
03526 
03527       /*
03528       ** Dead and dependent -> dead
03529       */
03530       
03531       if (alkind_isDependent (other->aliaskind) && res->defstate == SS_DEAD)
03532         {
03533           other->aliaskind = AK_UNKNOWN;
03534           other->defstate = SS_DEAD;
03535           sRef_clearDerived (res);
03536           sRef_clearDerived (other);
03537                 }
03538 
03539       if (alkind_isDependent (res->aliaskind) && other->defstate == SS_DEAD)
03540         {
03541           res->aliaskind = AK_UNKNOWN;
03542           res->defstate = SS_DEAD;
03543           sRef_clearDerived (res);
03544           sRef_clearDerived (other);
03545         }
03546 
03547       /*
03548       ** must do alias combine first, since it depends on 
03549       ** original values of state and null.
03550       */
03551 
03552       sRef_combineAliasKinds (res, other, cl, loc);
03553       sRef_combineDefState (res, other);
03554       sRef_combineNullState (res, other);
03555 
03556       if (rdef == SS_ALLOCATED || rdef == SS_SPECIAL)
03557         {
03558           if (odef == SS_DEFINED)
03559             {
03560               if (onull == NS_DEFNULL || onull == NS_CONSTNULL)
03561                 {
03562                   res->deriv = sRefSet_copy (res->deriv, other->deriv);
03563                 }
03564 
03565                               ; 
03566             }
03567           else if (odef == SS_ALLOCATED
03568                    || odef == SS_SPECIAL)
03569             {
03570               
03571               if (doDerivs)
03572                 {
03573                   if (ctype_isUnion (ctype_realType (sRef_getType (res))))
03574                     {
03575                       res->deriv = sRef_mergeUnionDerivs (res->deriv, 
03576                                                           other->deriv, 
03577                                                           opt, cl, loc);
03578                     }
03579                   else
03580                     {
03581                                       res->deriv = sRef_mergeDerivs (res->deriv, other->deriv, 
03582                                                      opt, cl, loc);
03583                     }
03584                 }
03585             }
03586           else
03587             {
03588               if (doDerivs)
03589                 {
03590                                   res->deriv = sRef_mergeDerivs (res->deriv, other->deriv, 
03591                                                  opt, cl, loc);
03592                 }
03593               else
03594                 {
03595                                 }
03596             }
03597         }
03598       else
03599         {
03600           if (rdef == SS_PDEFINED
03601               || (rdef == SS_DEFINED && odef == SS_PDEFINED))
03602             {
03603               if (doDerivs)
03604                 {
03605                                   res->deriv = sRef_mergePdefinedDerivs (res->deriv, other->deriv, 
03606                                                          opt, cl, loc);
03607                 }
03608             }
03609           else
03610             {
03611               if ((rdef == SS_DEFINED  || rdef == SS_UNKNOWN)
03612                   && res->defstate == SS_ALLOCATED)
03613                 {
03614                                   res->deriv = sRefSet_copy (res->deriv, other->deriv);
03615                 }
03616               else
03617                 {
03618                   if (doDerivs)
03619                     {
03620                                       res->deriv = sRef_mergeDerivs (res->deriv, other->deriv, 
03621                                                      opt, cl, loc);
03622                     }
03623                 }
03624             }
03625         }
03626 
03627       
03628       sRef_combineExKinds (res, other);
03629     }
03630   else
03631     {
03632       if (res->kind == SK_ARRAYFETCH && other->kind == SK_PTR)
03633         {
03634           sRef nother = sRef_buildArrayFetchKnown (sRef_getBase (other), 0);
03635 
03636           sRef_copyState (nother, other);
03637           sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
03638         }
03639       else if (res->kind == SK_PTR && other->kind == SK_ARRAYFETCH)
03640         {
03641           sRef nother = sRef_buildPointer (sRef_getBase (other));
03642 
03643           if (sRef_isValid (nother))
03644             {
03645               sRef_copyState (nother, other);
03646               sRef_mergeStateAux (res, nother, cl, opt, loc, doDerivs);
03647             }
03648         }
03649       else
03650         {
03651           llcontbug (message ("merge conj: %q / %q", sRef_unparseFull (res), 
03652                               sRef_unparseFull (other)));
03653           
03654         }
03655     }
03656   
03657   }
03658 
03659 static sRefSet
03660 sRef_mergeUnionDerivs (/*@only@*/ sRefSet res, 
03661                        /*@exposed@*/ sRefSet other, bool opt,
03662                        clause cl, fileloc loc)
03663 {
03664   if (sRefSet_isEmpty (res))
03665     {
03666       return sRefSet_copy (res, other);
03667     }
03668   else
03669     {
03670       sRefSet_allElements (other, el)
03671         {
03672           if (sRef_isValid (el))
03673             {
03674               sRef e2 = sRefSet_lookupMember (other, el);
03675               
03676               if (sRef_isValid (e2))
03677                 {
03678                   sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
03679                 }
03680               else
03681                 {
03682                   res = sRefSet_insert (res, el);
03683                 }
03684             }
03685         } end_sRefSet_allElements ;
03686 
03687       return res;
03688     }
03689 }
03690 
03691 static /*@only@*/ sRefSet
03692 sRef_mergeDerivs (/*@only@*/ sRefSet res, sRefSet other, 
03693                   bool opt, clause cl, fileloc loc)
03694 {
03695   sRefSet ret = sRefSet_new ();
03696   
03697     
03698   sRefSet_allElements (res, el)
03699     {
03700       if (sRef_isValid (el))
03701         {
03702           sRef e2 = sRefSet_lookupMember (other, el);
03703 
03704           if (sRef_isValid (e2))
03705             {
03706               if (el->defstate == SS_ALLOCATED &&
03707                   e2->defstate == SS_PDEFINED)
03708                 {
03709                   e2->defstate = SS_ALLOCATED;
03710                 }
03711               else if (e2->defstate == SS_ALLOCATED &&
03712                        el->defstate == SS_PDEFINED)
03713                 {
03714                   el->defstate = SS_ALLOCATED;
03715                   sRef_clearDerived (el);
03716                 }
03717               else if ((el->defstate == SS_DEAD || sRef_isKept (el)) &&
03718                        (e2->defstate == SS_DEFINED && !sRef_isKept (e2)))
03719                 {
03720                   
03721                   if (checkDeadState (el, TRUE, loc))
03722                     {
03723                       if (sRef_isThroughArrayFetch (el))
03724                         {
03725                           sRef_maybeKill (el, loc);
03726                           sRef_maybeKill (e2, loc);
03727                         }
03728                     }
03729                 }
03730               else if ((e2->defstate == SS_DEAD || sRef_isKept (e2)) &&
03731                        (el->defstate == SS_DEFINED && !sRef_isKept (el)))
03732                 {
03733                   
03734                   if (checkDeadState (e2, FALSE, loc))
03735                     {
03736                       if (sRef_isThroughArrayFetch (el))
03737                         {
03738                           sRef_maybeKill (el, loc);
03739                           sRef_maybeKill (e2, loc);
03740                         }
03741                     }
03742                 }
03743               else if (el->defstate == SS_DEFINED &&
03744                        e2->defstate == SS_PDEFINED)
03745                 {
03746                   el->defstate = SS_PDEFINED;
03747                 }
03748               else if (e2->defstate == SS_DEFINED &&
03749                        el->defstate == SS_PDEFINED)
03750                 {
03751                   e2->defstate = SS_PDEFINED;
03752                 }
03753               else
03754                 {
03755                   ; /* okay */
03756                 }
03757 
03758               if (ctype_isUnion (ctype_realType (sRef_getType (el))))
03759                 {
03760                   el->deriv = sRef_mergeUnionDerivs (el->deriv, e2->deriv, 
03761                                                      opt, cl, loc); 
03762                 }
03763               else
03764                 {
03765                   el->deriv = sRef_mergeDerivs (el->deriv, e2->deriv, opt, cl, loc); 
03766                 }
03767               
03768               if (sRef_equivalent (el, e2))
03769                 {
03770                                   ret = sRefSet_insert (ret, el);
03771                 }
03772               else
03773                 {
03774                   sRef sr = sRef_leastCommon (el, e2);
03775 
03776                   if (sRef_isValid (sr))
03777                     {
03778                       ret = sRefSet_insert (ret, sr);
03779                     }
03780                   else
03781                     {
03782                       ;
03783                     }
03784                 }
03785               
03786               (void) sRefSet_delete (other, e2);
03787             }
03788           else /* not defined */
03789             {
03790                       (void) checkDeadState (el, TRUE, loc);
03791             }
03792         }
03793     } end_sRefSet_allElements;
03794 
03795   sRefSet_allElements (other, el)
03796     {
03797       if (sRef_isValid (el))
03798         {
03799           (void) checkDeadState (el, FALSE, loc);
03800         }
03801     } end_sRefSet_allElements;
03802   
03803   sRefSet_free (res); 
03804   return (ret);
03805 }
03806 
03807 /*
03808 ** Returns TRUE is there is an error.
03809 */
03810 
03811 static bool checkDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
03812 {
03813   /*
03814   ** usymtab_isGuarded --- the utab should still be in the
03815   ** state of the alternate branch.
03816   **
03817   ** tbranch TRUE means el is released in the last branch, e.g.
03818   **     if (x != NULL) { ; } else { sfree (x); }
03819   ** so, if x is null in the other branch no error is reported.
03820   **
03821   ** tbranch FALSE means this is the other branch:
03822   **     if (x != NULL) { sfree (x); } else { ; }
03823   ** so, if x is null in this branch there is no error.
03824   */
03825 
03826   
03827   if ((sRef_isDead (el) || sRef_isKept (el))
03828       && !sRef_isDeepUnionField (el) && !sRef_isThroughArrayFetch (el))
03829     {
03830        
03831       if (!tbranch)
03832         {
03833           if (usymtab_isProbableDeepNull (el))
03834             {
03835                       return TRUE;
03836             }
03837         }
03838       else
03839         {
03840           if (usymtab_isAltProbablyDeepNull (el))
03841             {
03842                       return TRUE;
03843             }
03844         }
03845 
03846       if (optgenerror
03847           (FLG_BRANCHSTATE,
03848            message ("Storage %q is %q in one path, but live in another.",
03849                     sRef_unparse (el),
03850                     cstring_makeLiteral (sRef_isKept (el) 
03851                                          ? "kept" : "released")),
03852            loc))
03853         {
03854                   
03855           if (sRef_isKept (el))
03856             {
03857               sRef_showAliasInfo (el);      
03858             }
03859           else
03860             {
03861               sRef_showStateInfo (el);
03862             }
03863 
03864           /* prevent further errors */
03865           el->defstate = SS_UNKNOWN; 
03866           sRef_setAliasKind (el, AK_ERROR, fileloc_undefined);
03867           
03868           return FALSE;
03869         }
03870     }
03871 
03872   return TRUE;
03873 }
03874 
03875 static void 
03876 checkDerivDeadState (/*@notnull@*/ sRef el, bool tbranch, fileloc loc)
03877 {
03878   
03879   if (checkDeadState (el, tbranch, loc))
03880     {
03881       sRefSet_allElements (el->deriv, t)
03882         {
03883           if (sRef_isValid (t))
03884             {
03885                       checkDerivDeadState (t, tbranch, loc);
03886             }
03887         } end_sRefSet_allElements;
03888     }
03889 }
03890 
03891 static sRefSet
03892   sRef_mergePdefinedDerivs (sRefSet res, sRefSet other, bool opt, 
03893                             clause cl, fileloc loc)
03894 {
03895   sRefSet ret = sRefSet_new ();
03896 
03897   sRefSet_allElements (res, el)
03898     {
03899       if (sRef_isValid (el))
03900         {
03901           sRef e2 = sRefSet_lookupMember (other, el);
03902           
03903           if (sRef_isValid (e2))
03904             {
03905               if (sRef_isAllocated (el) && !sRef_isAllocated (e2))
03906                 {
03907                   ;
03908                 }
03909               else if (sRef_isAllocated (e2) && !sRef_isAllocated (el))
03910                 {
03911                   el->deriv = sRefSet_copy (el->deriv, e2->deriv); 
03912                 }
03913               else
03914                 {
03915                   el->deriv = sRef_mergePdefinedDerivs (el->deriv, e2->deriv, 
03916                                                         opt, cl, loc);
03917                 }
03918 
03919               sRef_mergeStateAux (el, e2, cl, opt, loc, FALSE);
03920               
03921               ret = sRefSet_insert (ret, el);
03922               (void) sRefSet_delete (other, e2);
03923             }
03924           else
03925             {
03926               if (!opt)
03927                 {
03928                                   checkDerivDeadState (el, (cl == FALSECLAUSE), loc);
03929                 }
03930 
03931               ret = sRefSet_insert (ret, el);
03932             }
03933         }
03934     } end_sRefSet_allElements;
03935   
03936   sRefSet_allElements (other, el)
03937     {
03938       if (sRef_isValid (el))
03939         {
03940           if (!sRefSet_member (ret, el))
03941             {
03942                               /* was cl == FALSECLAUSE */
03943               checkDerivDeadState (el, FALSE, loc);
03944               ret = sRefSet_insert (ret, el);
03945             }
03946           else
03947             {
03948               /*
03949               ** it's okay --- member is a different equality test 
03950               */
03951             }
03952         }
03953     } end_sRefSet_allElements;
03954 
03955   sRefSet_free (res);
03956   return (ret);
03957 }
03958 
03959 sRef sRef_makeConj (/*@exposed@*/ /*@returned@*/ sRef a, /*@exposed@*/ sRef b)
03960 {
03961   llassert (sRef_isValid (a));
03962   llassert (sRef_isValid (b));
03963       
03964   if (!sRef_equivalent (a, b))
03965     {
03966       sRef s = sRef_new ();
03967       
03968       s->kind = SK_CONJ;
03969       s->info = (sinfo) dmalloc (sizeof (*s->info));
03970       s->info->conj = (cjinfo) dmalloc (sizeof (*s->info->conj));
03971       s->info->conj->a = a;
03972       s->info->conj->b = b;
03973       
03974       if (ctype_equal (a->type, b->type)) s->type = a->type;
03975       else s->type = ctype_makeConj (a->type, b->type);
03976       
03977       if (a->defstate == b->defstate)
03978         {
03979           s->defstate = a->defstate;
03980         }
03981       else
03982         {
03983           s->defstate = SS_UNKNOWN; 
03984         }
03985       
03986       s->nullstate = NS_UNKNOWN;
03987       
03988       s->safe = a->safe && b->safe;
03989       s->aliaskind = alkind_resolve (a->aliaskind, b->aliaskind);
03990 
03991       return s;
03992     }
03993   else
03994     {
03995       /*@-exposetrans@*/ return a; /*@=exposetrans@*/
03996     }
03997 }
03998 
03999 sRef
04000 sRef_makeUnknown ()
04001 {
04002   sRef s = sRef_new ();
04003 
04004   s->kind = SK_UNKNOWN;
04005   return s;
04006 }
04007 
04008 static sRef
04009 sRef_makeSpecial (speckind sk) /*@*/
04010 {
04011   sRef s = sRef_new ();
04012 
04013   s->kind = SK_SPECIAL;
04014   s->info = (sinfo) dmalloc (sizeof (*s->info));
04015   s->info->spec = sk;
04016   return s;
04017 }
04018 
04019 static sRef srnothing = sRef_undefined;
04020 static sRef srinternal = sRef_undefined;
04021 static sRef srsystem = sRef_undefined;
04022 static sRef srspec = sRef_undefined;
04023 
04024 sRef
04025 sRef_makeNothing (void)
04026 {
04027   if (sRef_isInvalid (srnothing))
04028     {
04029       srnothing = sRef_makeSpecial (SR_NOTHING);
04030     }
04031 
04032   /*@-retalias@*/
04033   return srnothing;
04034   /*@=retalias@*/
04035 }
04036 
04037 sRef
04038 sRef_makeInternalState (void)
04039 {
04040   if (sRef_isInvalid (srinternal))
04041     {
04042       srinternal = sRef_makeSpecial (SR_INTERNAL);
04043     }
04044 
04045   /*@-retalias@*/
04046   return srinternal;
04047   /*@=retalias@*/
04048 }
04049 
04050 sRef
04051 sRef_makeSpecState (void)
04052 {
04053   if (sRef_isInvalid (srspec))
04054     {
04055       srspec = sRef_makeSpecial (SR_SPECSTATE);
04056     }
04057 
04058   /*@-retalias@*/
04059   return srspec;
04060   /*@=retalias@*/
04061 }
04062 
04063 sRef
04064 sRef_makeSystemState (void)
04065 {
04066   if (sRef_isInvalid (srsystem))
04067     {
04068       srsystem = sRef_makeSpecial (SR_SYSTEM);
04069     }
04070 
04071   /*@-retalias@*/
04072   return (srsystem);
04073   /*@=retalias@*/
04074 }
04075 
04076 static sRef
04077 sRef_makeResultType (ctype ct)
04078 {
04079   sRef res = sRef_makeResult ();
04080 
04081   res->type = ct;
04082   return res;
04083 }
04084 
04085 sRef
04086 sRef_makeResult ()
04087 {
04088   sRef s = sRef_new ();
04089   
04090   s->kind = SK_RESULT;
04091   s->type = ctype_unknown;
04092   s->defstate = SS_UNKNOWN; 
04093   s->aliaskind = AK_UNKNOWN;
04094   s->nullstate = NS_UNKNOWN;
04095   
04096   return s;
04097 }
04098 
04099 
04100 bool
04101 sRef_isNothing (sRef s)
04102 {
04103   return (sRef_isKindSpecial (s) && s->info->spec == SR_NOTHING);
04104 }
04105 
04106 bool
04107 sRef_isInternalState (sRef s)
04108 {
04109   return (sRef_isKindSpecial (s) && s->info->spec == SR_INTERNAL);
04110 }
04111 
04112 bool
04113 sRef_isSpecInternalState (sRef s)
04114 {
04115   return (sRef_isKindSpecial (s) 
04116           && (s->info->spec == SR_INTERNAL || s->info->spec == SR_SPECSTATE));
04117 }
04118 
04119 bool
04120 sRef_isSpecState (sRef s)
04121 {
04122   return (sRef_isKindSpecial (s) && s->info->spec == SR_SPECSTATE);
04123 }
04124 
04125 bool
04126 sRef_isResult (sRef s)
04127 {
04128   return (sRef_isValid (s) && s->kind == SK_RESULT);
04129 }
04130 
04131 bool
04132 sRef_isSystemState (sRef s)
04133 {
04134   return (sRef_isKindSpecial (s) && s->info->spec == SR_SYSTEM);
04135 }
04136 
04137 usymId
04138 sRef_getScopeIndex (sRef s)
04139 {
04140   llassert (sRef_isValid (s));
04141   llassert (sRef_isCvar (s));
04142 
04143   return (s->info->cvar->index);
04144 }
04145 
04146 void
04147 sRef_makeSafe (sRef s)
04148 {
04149   if (sRef_isValid (s)) 
04150     {
04151       s->safe = TRUE;
04152     }
04153 }
04154 
04155 void
04156 sRef_makeUnsafe (sRef s)
04157 {
04158   if (sRef_isValid (s)) 
04159     {
04160       s->safe = FALSE;
04161     }
04162 }
04163 
04164 /*
04165 ** memory state operations
04166 */
04167 
04168 /*@only@*/ cstring sRef_unparseFull (sRef s)
04169 {
04170   if (sRef_isInvalid (s)) return (cstring_undefined);
04171 
04172   return (message ("[%d] %q - %q [%s] { %q }", 
04173                    (int) s,
04174                    sRef_unparseDebug (s), 
04175                    sRef_unparseState (s),
04176                    exkind_unparse (s->oexpkind),
04177                    sRefSet_unparseDebug (s->deriv)));
04178 }
04179 
04180 /*@unused@*/ cstring sRef_unparseDeep (sRef s)
04181 {
04182   cstring st = cstring_undefined;
04183 
04184   st = message ("%q:", sRef_unparseFull (s));
04185 
04186   if (sRef_isValid (s))
04187     {
04188       sRefSet_allElements (s->deriv, el)
04189         {
04190           st = message("%q\n%q", st, sRef_unparseDeep (el));
04191         } end_sRefSet_allElements ;
04192     }
04193 
04194   return st;
04195 }
04196 
04197 /*@only@*/ cstring sRef_unparseState (sRef s)
04198 {
04199   if (sRef_isConj (s))
04200     {
04201       return (message ("%q | %q", 
04202                        sRef_unparseState (s->info->conj->a),
04203                        sRef_unparseState (s->info->conj->b)));
04204     }
04205 
04206   if (sRef_isInvalid (s))
04207     {
04208       return (cstring_makeLiteral ("<invalid>"));
04209     }
04210 
04211   return (message ("%s.%s.%s.%s", 
04212                    alkind_unparse (s->aliaskind), 
04213                    nstate_unparse (s->nullstate),
04214                    exkind_unparse (s->expkind),
04215                    sstate_unparse (s->defstate)));
04216 }
04217 
04218 bool sRef_isNotUndefined (sRef s)
04219 {
04220   return (sRef_isInvalid (s)
04221           || (s->defstate != SS_UNDEFINED
04222               && s->defstate != SS_UNUSEABLE
04223               && s->defstate != SS_DEAD));
04224 }
04225 
04226 ynm sRef_isWriteable (sRef s)
04227 {
04228   if (sRef_isInvalid (s)) return MAYBE;
04229 
04230   if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
04231     {
04232       if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjA (s))))
04233         {
04234           if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
04235             {
04236               return YES;
04237             }
04238           return MAYBE;
04239         }
04240       else
04241         {
04242           if (ynm_toBoolStrict (sRef_isWriteable (sRef_getConjB (s))))
04243             {
04244               return MAYBE;
04245             }
04246           return NO;
04247         }
04248     }
04249 
04250   return (ynm_fromBool (s->defstate != SS_UNUSEABLE));
04251 }
04252 
04253 bool sRef_hasNoStorage (sRef s)
04254 {
04255   return (!sRef_isAllocatedStorage (s) || sRef_isDefinitelyNull (s));
04256 }
04257 
04258 bool sRef_isStrictReadable (sRef s)
04259 {
04260   return (ynm_toBoolStrict (sRef_isReadable (s)));
04261 }
04262 
04263 ynm sRef_isReadable (sRef s)
04264 {
04265   sstate ss;
04266 
04267   if (sRef_isInvalid (s)) return YES;
04268 
04269   ss = s->defstate;
04270   
04271   if (sRef_isConj (s) && s->defstate == SS_UNKNOWN)
04272     {
04273       if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjA (s))))
04274         {
04275           if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
04276             {
04277               return YES;
04278             }
04279           return MAYBE;
04280         }
04281       else
04282         {
04283           if (ynm_toBoolStrict (sRef_isReadable (sRef_getConjB (s))))
04284             {
04285               return MAYBE;
04286             }
04287           return NO;
04288         }
04289     }
04290   else if (ss == SS_HOFFA)
04291     {
04292       if (context_getFlag (FLG_STRICTUSERELEASED))
04293         {
04294           return MAYBE;
04295         }
04296       else
04297         {
04298           return YES;
04299         }
04300     }
04301   else
04302     {
04303       return (ynm_fromBool (ss == SS_DEFINED 
04304                             || ss == SS_FIXED 
04305                             || ss == SS_RELDEF 
04306                             || ss == SS_PDEFINED 
04307                             || ss == SS_PARTIAL
04308                             || ss == SS_SPECIAL
04309                             || ss == SS_ALLOCATED
04310                             || ss == SS_UNKNOWN));
04311     }
04312 }
04313 
04314 static /*@exposed@*/ sRef whatUndefined (/*@exposed@*/ sRef fref, int depth)
04315 {
04316   ctype ct;
04317 
04318   
04319   if (depth > MAXDEPTH)
04320     {
04321       llgenmsg (message 
04322                 ("Warning: check definition limit exceeded, checking %q. "
04323                  "This either means there is a variable with at least "
04324                  "%d indirections apparent in the program text, or "
04325                  "there is a bug in LCLint.",
04326                  sRef_unparse (fref),
04327                  MAXDEPTH),
04328                 g_currentloc);
04329 
04330       return sRef_undefined;
04331     }
04332 
04333   if (!sRef_isKnown (fref) || sRef_isAnyDefined (fref))
04334     {
04335       return sRef_undefined;
04336     }
04337 
04338   if (sRef_isUnuseable (fref) || sRef_isStateUndefined (fref))
04339     {
04340       return fref;
04341     }
04342 
04343   ct = ctype_realType (sRef_getType (fref));
04344   
04345   if (ctype_isUnknown (ct))
04346     {
04347       return sRef_undefined;
04348     }
04349   else if (ctype_isPointer (ct) || ctype_isArray (ct))
04350     {
04351       if (sRef_isStateUnknown (fref))
04352         {
04353           return sRef_undefined;
04354         }
04355       else
04356         {
04357           sRef fptr = sRef_constructDeref (fref);
04358 
04359           return (whatUndefined (fptr, depth + 1));
04360         }
04361     }
04362   else if (ctype_isStruct (ct))
04363     {
04364       bool hasOneDefined = FALSE;
04365       
04366       if (sRef_isStateUnknown (fref))
04367         {
04368           return fref;
04369         }
04370           
04371       if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
04372         {
04373           sRefSet_realElements (sRef_derivedFields (fref), sr)
04374             {
04375               hasOneDefined = TRUE;
04376               
04377               if (sRef_isField (sr))
04378                 {
04379                   cstring fieldname = sRef_getField (sr);
04380                   sRef fldref = sRef_makeField (fref, fieldname);
04381                   bool shouldCheck = !sRef_isRecursiveField (fldref);
04382                   
04383                   if (shouldCheck)
04384                     {
04385                       sRef wdef = whatUndefined (fldref, depth + 1);
04386 
04387                       if (sRef_isValid (wdef))
04388                         {
04389                           return wdef;
04390                         }
04391                     }
04392                 }
04393             } end_sRefSet_realElements;
04394         }
04395       else if (sRef_isAllocated (fref))
04396         {
04397           /*
04398           ** for structures, each field must be completely defined
04399           */
04400           
04401           uentryList fields = ctype_getFields (ct);
04402               
04403           uentryList_elements (fields, ue)
04404             {
04405               cstring name = uentry_getRealName (ue);
04406               sRef ffield = sRef_makeField (fref, name);
04407               bool shouldCheck = !sRef_isRecursiveField (ffield);
04408 
04409               if (sRef_isRelDef (uentry_getSref (ue)))
04410                 {
04411                   ; /* no error */
04412                 }
04413               else
04414                 {
04415                   if (shouldCheck)
04416                     {
04417                       sRef wdef = whatUndefined (ffield, depth + 1);
04418 
04419                       if (sRef_isInvalid (wdef))
04420                         {
04421                           return wdef;
04422                         }
04423                     }
04424                 }
04425             } end_uentryList_elements;
04426         }
04427       else
04428         {
04429           ;
04430         }
04431     }
04432   else if (ctype_isUnion (ct))
04433     {
04434       ; 
04435     }
04436   else
04437     {
04438       ;
04439     }
04440 
04441   return sRef_undefined;
04442 }
04443 
04444 static bool checkDefined (sRef sr)
04445 {
04446   return (sRef_isInvalid (whatUndefined (sr, 0)));
04447 }
04448 
04449 bool sRef_isReallyDefined (sRef s)
04450 {
04451   if (sRef_isValid (s))
04452     {
04453       if (sRef_isAnyDefined (s))
04454         {
04455           return TRUE;
04456         }
04457       else
04458         {
04459           if (sRef_isAllocated (s) || sRef_isPdefined (s))
04460             {
04461               return checkDefined (s);
04462             }
04463           else
04464             {
04465               return FALSE;
04466             }
04467         }
04468     }
04469   else
04470     {
04471       return TRUE;
04472     }
04473 }
04474 
04475 void sRef_showNotReallyDefined (sRef s)
04476 {
04477   if (sRef_isValid (s))
04478     {
04479       if (sRef_isAnyDefined (s))
04480         {
04481           BADBRANCH;
04482         }
04483       else
04484         {
04485           if (sRef_isAllocated (s) || sRef_isPdefined (s))
04486             {
04487               sRef ref = whatUndefined (s, 0);
04488 
04489               llassert (sRef_isValid (ref));
04490 
04491               if (ref != s)
04492                 {
04493                   llgenindentmsgnoloc
04494                     (message ("This sub-reference is %s: %q",
04495                               sstate_unparse (sRef_getDefState (ref)),
04496                               sRef_unparse (ref)));
04497                 }
04498             }
04499           else
04500             {
04501               ;
04502             }
04503         }
04504     }
04505   else
04506     {
04507       BADBRANCH;
04508     }
04509 }
04510 
04511 sstate sRef_getDefState (sRef s)
04512 {
04513   if (sRef_isInvalid (s)) return (SS_UNKNOWN);
04514   return (s->defstate);
04515 }
04516 
04517 void sRef_setDefState (sRef s, sstate defstate, fileloc loc)
04518 {
04519   sRef_setStateAux (s, defstate, loc);
04520 }
04521 
04522 static void sRef_clearAliasStateAux (sRef s, fileloc loc)
04523 {
04524   sRef_setAliasKind (s, AK_ERROR, loc);
04525 }
04526 
04527 void sRef_clearAliasState (sRef s, fileloc loc)
04528 {
04529   sRef_aliasSetComplete (sRef_clearAliasStateAux, s, loc);
04530 }
04531 
04532 void sRef_setAliasKindComplete (sRef s, alkind kind, fileloc loc)
04533 {
04534   sRef_aliasSetCompleteParam (sRef_setAliasKind, s, kind, loc);
04535 }
04536 
04537 void sRef_setAliasKind (sRef s, alkind kind, fileloc loc)
04538 {
04539   if (sRef_isValid (s))
04540     {
04541       sRef_clearDerived (s);
04542 
04543       if ((kind != s->aliaskind && kind != s->oaliaskind)
04544           && fileloc_isDefined (loc))
04545         {
04546           s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
04547         }
04548       
04549       s->aliaskind = kind;
04550     }
04551 }
04552 
04553 void sRef_setOrigAliasKind (sRef s, alkind kind)
04554 {
04555   if (sRef_isValid (s))
04556     {
04557       s->oaliaskind = kind;
04558     }
04559 }
04560 
04561 exkind sRef_getExKind (sRef s)
04562 {
04563   if (sRef_isValid (s))
04564     {
04565       return (s->expkind);
04566     }
04567   else
04568     {
04569       return XO_UNKNOWN;
04570     }
04571 }
04572 
04573 exkind sRef_getOrigExKind (sRef s)
04574 {
04575   if (sRef_isValid (s))
04576     {
04577       return (s->oexpkind);
04578     }
04579   else
04580     {
04581       return XO_UNKNOWN;
04582     }
04583 }
04584 
04585 static void sRef_clearExKindAux (sRef s, fileloc loc)
04586 {
04587   sRef_setExKind (s, XO_UNKNOWN, loc);
04588 }
04589 
04590 void sRef_setObserver (sRef s, fileloc loc) 
04591 {
04592   sRef_setExKind (s, XO_OBSERVER, loc);
04593 }
04594 
04595 void sRef_setExposed (sRef s, fileloc loc) 
04596 {
04597   sRef_setExKind (s, XO_EXPOSED, loc);
04598 }
04599 
04600 void sRef_clearExKindComplete (sRef s, fileloc loc)
04601 {
04602   (void) sRef_aliasSetComplete (sRef_clearExKindAux, s, loc);
04603 }
04604 
04605 void sRef_setExKind (sRef s, exkind exp, fileloc loc)
04606 {
04607   if (sRef_isValid (s))
04608     {
04609       if (s->expkind != exp)
04610         {
04611           s->expinfo = alinfo_updateLoc (s->expinfo, loc);
04612         }
04613       
04614       s->expkind = exp;
04615     }
04616 }
04617 
04618 /*
04619 ** s1->derived = s2->derived
04620 */
04621 
04622 static void sRef_copyRealDerived (sRef s1, sRef s2)
04623 {
04624   if (sRef_isValid (s1) && sRef_isValid (s2))
04625     {
04626       sRef sb = sRef_getRootBase (s1);
04627 
04628       sRefSet_clear (s1->deriv);
04629 
04630       sRefSet_allElements (s2->deriv, el)
04631         {
04632           if (sRef_isValid (el))
04633             {
04634               sRef rb = sRef_getRootBase (el);
04635               
04636               if (!sRef_same (rb, sb))
04637                 {
04638                   sRef fb = sRef_fixDirectBase (el, s1);
04639                   
04640                   if (sRef_isValid (fb))
04641                     {
04642                       sRef_copyRealDerived (fb, el);
04643                       sRef_addDeriv (s1, fb);
04644                     }
04645                 }
04646               else
04647                 {
04648                   sRef_addDeriv (s1, el);
04649                 }
04650             }
04651         } end_sRefSet_allElements ;
04652     }
04653   
04654   }
04655 
04656 void sRef_copyRealDerivedComplete (sRef s1, sRef s2)
04657 {
04658   sRef_innerAliasSetCompleteParam (sRef_copyRealDerived, s1, s2);
04659 }
04660 
04661 void sRef_setUndefined (sRef s, fileloc loc)
04662 {
04663   if (sRef_isValid (s))
04664     {
04665       s->defstate = SS_UNDEFINED;
04666 
04667       if (fileloc_isDefined (loc))
04668         {
04669           s->definfo = alinfo_updateLoc (s->definfo, loc);
04670         }
04671 
04672       sRef_clearDerived (s);
04673     }
04674 }
04675 
04676 static void sRef_setDefinedAux (sRef s, fileloc loc, bool clear)
04677 {
04678   if (sRef_isInvalid (s)) return;
04679 
04680   if (s->defstate != SS_DEFINED && fileloc_isDefined (loc))
04681     {
04682       s->definfo = alinfo_updateLoc (s->definfo, loc);
04683     }
04684   
04685   s->defstate = SS_DEFINED;
04686   
04687   /* e.g., if x is allocated, *x = 3 defines x */
04688   
04689   if (s->kind == SK_PTR)
04690     {
04691       sRef p = s->info->ref;
04692       
04693       if (p->defstate == SS_ALLOCATED)
04694         {
04695           sRef_setDefinedAux (p, loc, clear);
04696         }
04697     }
04698   else if (s->kind == SK_ARRAYFETCH) 
04699     {
04700       if (!s->info->arrayfetch->indknown
04701           || (s->info->arrayfetch->ind == 0))
04702         {
04703           sRef p = s->info->arrayfetch->arr;
04704           sRef ptr = sRef_constructPointer (p);
04705           
04706           if (sRef_isValid (ptr))
04707             {
04708               if (ptr->defstate == SS_ALLOCATED 
04709                   || ptr->defstate == SS_UNDEFINED)
04710                 {
04711                   sRef_setDefinedAux (ptr, loc, clear);
04712                 }
04713             }
04714           
04715           if (p->defstate == SS_RELDEF) 
04716             {
04717               ;
04718             }
04719           else if (p->defstate == SS_ALLOCATED || p->defstate == SS_PDEFINED)
04720             {
04721               p->defstate = SS_DEFINED;
04722             }
04723           else
04724             {
04725             }
04726         }
04727     }
04728   else if (s->kind == SK_FIELD)
04729     {
04730       sRef parent = s->info->field->rec;
04731       
04732       if (sRef_isValid (parent))
04733         {
04734           if (ctype_isUnion (ctype_realType (parent->type)))
04735             {
04736               /*
04737               ** Should not clear derived from here.
04738               */
04739               
04740               sRef_setDefinedNoClear (parent, loc);
04741             }
04742           else
04743             {
04744               ; /* Nothing to do for structures. */
04745             }
04746         }
04747 
04748           }
04749   else
04750     {
04751       ;
04752     }
04753 
04754   if (clear)
04755     {
04756       sRef_clearDerived (s);
04757     }  
04758 }
04759 
04760 static void sRef_setPartialDefined (sRef s, fileloc loc)
04761 {
04762   if (!sRef_isPartial (s))
04763     {
04764       sRef_setDefined (s, loc);
04765     }
04766 }
04767 
04768 void sRef_setPartialDefinedComplete (sRef s, fileloc loc)
04769 {
04770   sRef_innerAliasSetComplete (sRef_setPartialDefined, s, loc);
04771 }
04772 
04773 void sRef_setDefinedComplete (sRef s, fileloc loc)
04774 {
04775   sRef_innerAliasSetComplete (sRef_setDefined, s, loc);
04776 }
04777 
04778 void sRef_setDefined (sRef s, fileloc loc)
04779 {
04780   sRef_setDefinedAux (s, loc, TRUE);
04781 }
04782 
04783 static void sRef_setDefinedNoClear (sRef s, fileloc loc)
04784 {
04785   DPRINTF (("Defining: %s", sRef_unparseFull (s)));
04786   sRef_setDefinedAux (s, loc, FALSE);
04787   DPRINTF (("==> %s", sRef_unparseFull (s)));
04788 }
04789 
04790 void sRef_setDefinedNCComplete (sRef s, fileloc loc)
04791 {
04792   DPRINTF (("Set Defined Complete: %s", sRef_unparseFull (s)));
04793   sRef_innerAliasSetComplete (sRef_setDefinedNoClear, s, loc);
04794   DPRINTF (("==> %s", sRef_unparseFull (s)));
04795 }
04796 
04797 static bool sRef_isDeepUnionField (sRef s)
04798 {
04799   return (sRef_deepPred (sRef_isUnionField, s));
04800 }
04801 
04802 bool sRef_isUnionField (sRef s)
04803 {
04804   if (sRef_isValid (s) && s->kind == SK_FIELD)
04805     {
04806       /*
04807        ** defining one field of a union defines the union
04808        */
04809       
04810       sRef base = s->info->field->rec;
04811 
04812       if (sRef_isValid (base))
04813         {
04814           return (ctype_isUnion (ctype_realType (base->type)));
04815         }
04816     }
04817 
04818   return FALSE;
04819 }
04820 
04821 void sRef_setPdefined (sRef s, fileloc loc)
04822 {
04823   if (sRef_isValid (s) && !sRef_isPartial (s))
04824     {
04825       sRef base = sRef_getBaseSafe (s);
04826 
04827       if (s->defstate == SS_ALLOCATED)
04828         {
04829           return;
04830         }
04831       
04832       if (s->defstate != SS_PDEFINED && fileloc_isDefined (loc))
04833         {
04834           s->definfo = alinfo_updateLoc (s->definfo, loc);
04835         }
04836 
04837       s->defstate = SS_PDEFINED;
04838       
04839       /* e.g., if x is allocated, *x = 3 defines x */
04840       
04841       while (sRef_isValid (base) && sRef_isKnown (base))
04842         {
04843           if (base->defstate == SS_DEFINED)
04844             { 
04845               sRef nb;
04846 
04847                       base->defstate = SS_PDEFINED; 
04848               nb = sRef_getBaseSafe (base); 
04849               base = nb;
04850             }
04851           else 
04852             { 
04853               break; 
04854             }
04855         }      
04856     }
04857 }
04858 
04859 static void sRef_setStateAux (sRef s, sstate ss, fileloc loc)
04860 {
04861   if (sRef_isValid (s))
04862     {
04863       /* if (s->defstate == SS_RELDEF) return; */
04864 
04865       if (s->defstate != ss && fileloc_isDefined (loc))
04866         {
04867           s->definfo = alinfo_updateLoc (s->definfo, loc);
04868         }
04869 
04870       s->defstate = ss;
04871       sRef_clearDerived (s); 
04872 
04873       if (ss == SS_ALLOCATED)
04874         {
04875           sRef base = sRef_getBaseSafe (s);
04876           
04877           while (sRef_isValid (base) && sRef_isKnown (base))
04878             {
04879               if (base->defstate == SS_DEFINED) 
04880                 { 
04881                   sRef nb;
04882                   
04883                   base->defstate = SS_PDEFINED; 
04884                   
04885                   nb = sRef_getBaseSafe (base); 
04886                   base = nb;
04887                 }
04888               else 
04889                 { 
04890                   break; 
04891                 }
04892             }
04893         }
04894 
04895           }
04896 }
04897 
04898 void sRef_setAllocatedComplete (sRef s, fileloc loc)
04899 {
04900   sRef_innerAliasSetComplete (sRef_setAllocated, s, loc);
04901 }
04902 
04903 static void sRef_setAllocatedShallow (sRef s, fileloc loc)
04904 {
04905   if (sRef_isValid (s))
04906     {
04907       if (s->defstate == SS_DEAD || s->defstate == SS_UNDEFINED)
04908         {
04909           s->defstate = SS_ALLOCATED;
04910           
04911           if (fileloc_isDefined (loc))
04912             {
04913               s->definfo = alinfo_updateLoc (s->definfo, loc);
04914             }
04915         }
04916     }
04917 }
04918 
04919 void sRef_setAllocatedShallowComplete (sRef s, fileloc loc)
04920 {
04921   sRef_innerAliasSetComplete (sRef_setAllocatedShallow, s, loc);
04922 }
04923 
04924 void sRef_setAllocated (sRef s, fileloc loc)
04925 {
04926   sRef_setStateAux (s, SS_ALLOCATED, loc);
04927   }
04928 
04929 void sRef_setPartial (sRef s, fileloc loc)
04930 {
04931   sRef_setStateAux (s, SS_PARTIAL, loc);
04932   }
04933 
04934 void sRef_setShared (sRef s, fileloc loc)
04935 {
04936   if (sRef_isValid (s))
04937     {
04938       if (s->aliaskind != AK_SHARED && fileloc_isDefined (loc))
04939         {
04940           s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
04941         }
04942 
04943       s->aliaskind = AK_SHARED;
04944       /* don't! sRef_clearDerived (s); */
04945     }
04946 }
04947 
04948 void sRef_setLastReference (sRef s, sRef ref, fileloc loc)
04949 {
04950   if (sRef_isValid (s))
04951     {
04952       s->aliaskind = sRef_getAliasKind (ref);
04953       s->aliasinfo = alinfo_updateRefLoc (s->aliasinfo, ref, loc);
04954     }
04955 }
04956 
04957 static
04958 void sRef_setNullStateAux (/*@notnull@*/ sRef s, nstate ns, fileloc loc)
04959 {
04960  s->nullstate = ns;
04961 
04962  if (fileloc_isDefined (loc))
04963    {
04964      s->nullinfo = alinfo_updateLoc (s->nullinfo, loc);
04965    }
04966 }
04967 
04968 void sRef_setNotNull (sRef s, fileloc loc)
04969 {
04970   if (sRef_isValid (s))
04971     {
04972       sRef_setNullStateAux (s, NS_NOTNULL, loc);
04973     }
04974 }
04975 
04976 void sRef_setNullState (sRef s, nstate n, fileloc loc)
04977 {
04978   if (sRef_isValid (s))
04979     {
04980       sRef_setNullStateAux (s, n, loc);
04981     }
04982 }
04983 
04984 void sRef_setNullStateInnerComplete (sRef s, nstate n, fileloc loc)
04985 {
04986   sRef_setNullState (s, n, loc);
04987 
04988   switch (n)
04989     {
04990     case NS_POSNULL:
04991       sRef_innerAliasSetComplete (sRef_setPosNull, s, loc);
04992       break;
04993     case NS_DEFNULL:
04994       sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
04995       break;
04996     case NS_UNKNOWN:
04997       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
04998       break;
04999     case NS_NOTNULL:
05000       sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
05001       break;
05002     case NS_MNOTNULL:
05003       sRef_innerAliasSetComplete (sRef_setNotNull, s, loc);
05004       break;
05005     case NS_RELNULL:
05006       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
05007       break;
05008     case NS_CONSTNULL:
05009       sRef_innerAliasSetComplete (sRef_setDefNull, s, loc);
05010       break;
05011     case NS_ABSNULL:
05012       sRef_innerAliasSetComplete (sRef_setNullUnknown, s, loc);
05013       break;
05014     case NS_ERROR:
05015       sRef_innerAliasSetComplete (sRef_setNullErrorLoc, s, loc);
05016       break;
05017     }
05018 }
05019 
05020 void sRef_setPosNull (sRef s, fileloc loc)
05021 {
05022   if (sRef_isValid (s))
05023     {
05024       sRef_setNullStateAux (s, NS_POSNULL, loc);
05025     }
05026 }
05027   
05028 void sRef_setDefNull (sRef s, fileloc loc)
05029 {
05030   if (sRef_isValid (s))
05031     {
05032       sRef_setNullStateAux (s, NS_DEFNULL, loc);
05033     }
05034 }
05035 
05036 void sRef_setNullUnknown (sRef s, fileloc loc)
05037 {
05038   if (sRef_isValid (s))
05039     {
05040       sRef_setNullStateAux (s, NS_UNKNOWN, loc);
05041     }
05042 }
05043 
05044 void sRef_setNullError (sRef s)
05045 {
05046   if (sRef_isValid (s))
05047     {
05048       sRef_setNullStateAux (s, NS_UNKNOWN, fileloc_undefined);
05049     }
05050 }
05051 
05052 void sRef_setNullErrorLoc (sRef s, /*@unused@*/ fileloc loc)
05053 {
05054   sRef_setNullError (s);
05055 }
05056 
05057 void sRef_setOnly (sRef s, fileloc loc)
05058 {
05059   if (sRef_isValid (s) && s->aliaskind != AK_ONLY)
05060     {
05061       s->aliaskind = AK_ONLY;
05062       s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
05063           }
05064 }
05065 
05066 void sRef_setDependent (sRef s, fileloc loc)
05067 {
05068   if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_DEPENDENT))
05069     {
05070       s->aliaskind = AK_DEPENDENT;
05071       s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
05072           }
05073 }
05074 
05075 void sRef_setOwned (sRef s, fileloc loc)
05076 {
05077   if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_OWNED))
05078     {
05079       s->aliaskind = AK_OWNED;
05080       s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
05081           }
05082 }
05083 
05084 void sRef_setKept (sRef s, fileloc loc)
05085 {
05086   if (sRef_isValid (s) && !sRef_isConst (s) && (s->aliaskind != AK_KEPT))
05087     {
05088       sRef base = sRef_getBaseSafe (s);  
05089       
05090       while (sRef_isValid (base) && sRef_isKnown (base))
05091         {
05092           if (base->defstate == SS_DEFINED) 
05093             {
05094               base->defstate = SS_PDEFINED; 
05095                       base = sRef_getBaseSafe (base); 
05096             }
05097           else 
05098             {
05099               break; 
05100             }
05101 
05102         }
05103 
05104       s->aliaskind = AK_KEPT;
05105       s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
05106           }
05107 }
05108 
05109 static void sRef_setKeptAux (sRef s, fileloc loc)
05110 {
05111   if (!sRef_isShared (s))
05112     {
05113       sRef_setKept (s, loc);
05114     }
05115 }
05116 
05117 static void sRef_setDependentAux (sRef s, fileloc loc)
05118 {
05119   if (!sRef_isShared (s))
05120     {
05121       sRef_setDependent (s, loc);
05122     }
05123 }
05124 
05125 void sRef_setKeptComplete (sRef s, fileloc loc)
05126 {
05127   sRef_aliasSetComplete (sRef_setKeptAux, s, loc);
05128 }
05129 
05130 void sRef_setDependentComplete (sRef s, fileloc loc)
05131 {
05132   sRef_aliasSetComplete (sRef_setDependentAux, s, loc);
05133 }
05134 
05135 void sRef_setFresh (sRef s, fileloc loc)
05136 {
05137   if (sRef_isValid (s))
05138     {
05139       s->aliaskind = AK_FRESH;
05140       s->aliasinfo = alinfo_updateLoc (s->aliasinfo, loc);
05141     }
05142 }
05143 
05144 void sRef_kill (sRef s, fileloc loc)
05145 {
05146   DPRINTF (("Kill: %s", sRef_unparseFull (s)));
05147 
05148   if (sRef_isValid (s) && !sRef_isShared (s) && !sRef_isConst (s))
05149     {
05150       sRef base = sRef_getBaseSafe (s);  
05151       
05152       while (sRef_isValid (base) && sRef_isKnown (base))
05153         {
05154           if (base->defstate == SS_DEFINED) 
05155             {
05156               base->defstate = SS_PDEFINED; 
05157               base = sRef_getBaseSafe (base); 
05158             }
05159           else 
05160             {
05161               break; 
05162             }
05163 
05164         }
05165       
05166       s->aliaskind = s->oaliaskind;
05167       s->defstate = SS_DEAD;
05168       s->definfo = alinfo_updateLoc (s->definfo, loc);
05169 
05170       sRef_clearDerived (s);
05171     }
05172 }
05173 
05174 void sRef_maybeKill (sRef s, fileloc loc)
05175 {
05176         
05177   if (sRef_isValid (s))
05178     {
05179       sRef base = sRef_getBaseSafe (s);  
05180 
05181             
05182       while (sRef_isValid (base) && sRef_isKnown (base))
05183         {
05184           if (base->defstate == SS_DEFINED || base->defstate == SS_RELDEF)
05185             {
05186               base->defstate = SS_PDEFINED; 
05187                       base = sRef_getBaseSafe (base); 
05188             }
05189           else 
05190             {
05191                       break; 
05192             }
05193           
05194         }
05195       
05196       s->aliaskind = s->oaliaskind;
05197       s->defstate = SS_HOFFA; 
05198       s->definfo = alinfo_updateLoc (s->definfo, loc);
05199       sRef_clearDerived (s); 
05200     }
05201 
05202   }
05203 
05204 /*
05205 ** just for type checking...
05206 */
05207 
05208 static void sRef_killAux (sRef s, fileloc loc)
05209 {
05210   if (sRef_isValid (s) && !sRef_isShared (s))
05211     {
05212       if (sRef_isUnknownArrayFetch (s))
05213         {
05214           sRef_maybeKill (s, loc);
05215         }
05216       else
05217         {
05218                   sRef_kill (s, loc);
05219                 }
05220     }
05221 }
05222 
05223 /*
05224 ** kills s and all aliases to s
05225 */
05226 
05227 void sRef_killComplete (sRef s, fileloc loc)
05228 {
05229   DPRINTF (("Kill complete: %s", sRef_unparseFull (s)));
05230   sRef_aliasSetComplete (sRef_killAux, s, loc);
05231 }
05232 
05233 static bool sRef_equivalent (sRef s1, sRef s2)
05234 {
05235   return (sRef_compare (s1, s2) == 0);
05236 }
05237 
05238 /*
05239 ** returns an sRef that will not be free'd on function exit.
05240 */
05241 
05242 /*@only@*/ sRef sRef_saveCopy (sRef s)
05243 {
05244   sRef ret;
05245 
05246   if (sRef_isValid (s))
05247     {
05248       bool old = inFunction;
05249 
05250       /*
05251       ** Exit the function scope, so this sRef is not
05252       ** stored in the deallocation table.
05253       */
05254       
05255       inFunction = FALSE;
05256       DPRINTF (("Copying sref: %s", sRef_unparseFull(s)));
05257       ret = sRef_copy (s);
05258       DPRINTF (("Copying ===>: %s", sRef_unparseFull(ret)));
05259       inFunction = old;
05260     }
05261   else
05262     {
05263       ret = sRef_undefined;
05264     }
05265 
05266   /*@-dependenttrans@*/ 
05267   return ret;
05268   /*@=dependenttrans@*/ 
05269 }
05270 
05271 sRef sRef_copy (sRef s)
05272 {
05273   if (sRef_isKindSpecial (s))
05274     {
05275       /*@-retalias@*/
05276       return s; /* don't copy specials */
05277       /*@=retalias@*/
05278     }
05279   
05280   if (sRef_isValid (s))
05281     {
05282       sRef t = sRef_alloc ();
05283 
05284       t->kind = s->kind;
05285       t->safe = s->safe;
05286       t->modified = s->modified;
05287       t->type = s->type;
05288 
05289             t->info = sinfo_copy (s);
05290       
05291       t->defstate = s->defstate;
05292 
05293       t->nullstate = s->nullstate;
05294 
05295       t->aliaskind = s->aliaskind;
05296       t->oaliaskind = s->oaliaskind;
05297 
05298       t->expkind = s->expkind;
05299       t->oexpkind = s->oexpkind;
05300 
05301       t->aliasinfo = alinfo_copy (s->aliasinfo);
05302       t->definfo = alinfo_copy (s->definfo);
05303       t->nullinfo = alinfo_copy (s->nullinfo);
05304       t->expinfo = alinfo_copy (s->expinfo);
05305 
05306       t->deriv = sRefSet_newDeepCopy (s->deriv);
05307       
05308       return t;
05309     }
05310   else
05311     {
05312       return sRef_undefined;
05313     }
05314 }
05315 
05316 /*@notfunction@*/
05317 # define PREDTEST(func,s) \
05318    do { if (sRef_isInvalid (s)) { return FALSE; } \
05319         else { if (sRef_isConj (s)) \
05320                   { return (func (sRef_getConjA (s)) \
05321                             || func (sRef_getConjB (s))); }}} while (FALSE);
05322 
05323 bool sRef_isAddress (sRef s)
05324 {
05325   PREDTEST (sRef_isAddress, s);
05326   return (s->kind == SK_ADR);
05327 }
05328           
05329 /*
05330 ** pretty weak... maybe a flag should control this.
05331 */
05332 
05333 bool sRef_isThroughArrayFetch (sRef s)
05334 {
05335   if (sRef_isValid (s))
05336     {
05337       sRef tref = s;
05338 
05339       do 
05340         {
05341           sRef lt;
05342 
05343           if (sRef_isArrayFetch (tref)) 
05344             {
05345                       return TRUE;
05346             }
05347           
05348           lt = sRef_getBase (tref);
05349           tref = lt;
05350         } while (sRef_isValid (tref));
05351     } 
05352 
05353   return FALSE;
05354 }
05355 
05356 bool sRef_isArrayFetch (sRef s)
05357 {
05358   PREDTEST (sRef_isArrayFetch, s);
05359   return (s->kind == SK_ARRAYFETCH);
05360 }
05361 
05362 bool sRef_isMacroParamRef (sRef s)
05363 {
05364   if (context_inMacro () && sRef_isCvar (s))
05365     {
05366       uentry ue = sRef_getUentry (s);
05367       cstring pname = makeParam (uentry_rawName (ue));
05368       uentry mac = usymtab_lookupSafe (pname);
05369 
05370       cstring_free (pname);
05371       return (uentry_isValid (mac));
05372     }
05373 
05374   return FALSE;
05375 }
05376       
05377 bool sRef_isCvar (sRef s) 
05378 {
05379   PREDTEST (sRef_isCvar, s);
05380   return (s->kind == SK_CVAR);
05381 }
05382 
05383 bool sRef_isConst (sRef s) 
05384 {
05385   PREDTEST (sRef_isConst, s);
05386   return (s->kind == SK_CONST);
05387 }
05388 
05389 bool sRef_isObject (sRef s) 
05390 {
05391   PREDTEST (sRef_isObject, s);
05392   return (s->kind == SK_OBJECT);
05393 }
05394 
05395 bool sRef_isExternal (sRef s) 
05396 {
05397   PREDTEST (sRef_isExternal, s);
05398   return (s->kind == SK_EXTERNAL);
05399 }
05400 
05401 static bool sRef_isDerived (sRef s) 
05402 {
05403   PREDTEST (sRef_isDerived, s);
05404   return (s->kind == SK_DERIVED);
05405 }
05406 
05407 bool sRef_isField (sRef s)
05408 {
05409   PREDTEST (sRef_isField, s);
05410   return (s->kind == SK_FIELD);
05411 }
05412 
05413 static bool sRef_isIndex (sRef s)
05414 {
05415   PREDTEST (sRef_isIndex, s);
05416   return (s->kind == SK_ARRAYFETCH);
05417 }
05418 
05419 bool sRef_isAnyParam (sRef s)
05420 {
05421   PREDTEST (sRef_isAnyParam, s);
05422   return (s->kind == SK_PARAM);  
05423 }
05424 
05425 bool sRef_isParam (sRef s)
05426 {
05427   PREDTEST (sRef_isParam, s);
05428   return (s->kind == SK_PARAM);
05429 }
05430 
05431 bool sRef_isDirectParam (sRef s)
05432 {
05433   PREDTEST (sRef_isDirectParam, s);
05434 
05435   return ((s->kind == SK_CVAR) &&
05436           (s->info->cvar->lexlevel == functionScope) &&
05437           (context_inFunction () && 
05438            (s->info->cvar->index <= uentryList_size (context_getParams ()))));
05439 }
05440 
05441 bool sRef_isPointer (sRef s)
05442 {
05443   PREDTEST (sRef_isPointer, s);
05444   return (s->kind == SK_PTR);
05445 }
05446 
05447 /*
05448 ** returns true if storage referenced by s is visible
05449 */
05450 
05451 bool sRef_isReference (sRef s)
05452 {
05453   PREDTEST (sRef_isReference, s);
05454 
05455   return (sRef_isPointer (s) || sRef_isIndex (s) || sRef_isGlobal (s)
05456           || (sRef_isField (s) && (sRef_isReference (s->info->field->rec))));
05457 }
05458 
05459 bool sRef_isIReference (sRef s)
05460 {
05461   return (sRef_isPointer (s) || sRef_isAddress (s) || sRef_isIndex (s)
05462           || sRef_isField (s) || sRef_isArrayFetch (s));
05463 }
05464 
05465 bool sRef_isGlobal (sRef s)
05466 {
05467   return (sRef_isCvar (s) && (s->info->cvar->lexlevel <= fileScope));
05468 }
05469 
05470 bool sRef_isRealGlobal (sRef s)
05471 {
05472   return (sRef_isCvar (s) && (s->info->cvar->lexlevel == globScope));
05473 }
05474 
05475 bool sRef_isFileStatic (sRef s)
05476 {
05477   return (sRef_isCvar (s) && (s->info->cvar->lexlevel == fileScope));
05478 }
05479 
05480 bool sRef_isAliasCheckedGlobal (sRef s)
05481 {
05482   if (sRef_isGlobal (s))
05483     {
05484       uentry ue = sRef_getUentry (s);
05485 
05486       return context_checkAliasGlob (ue);
05487     }
05488   else
05489     {
05490       return FALSE;
05491     }
05492 }
05493 
05494 void sRef_free (/*@only@*/ sRef s)
05495 {
05496   if (s != sRef_undefined && s->kind != SK_SPECIAL)
05497     {
05498       alinfo_free (s->expinfo);
05499       alinfo_free (s->aliasinfo);
05500       alinfo_free (s->definfo);
05501       alinfo_free (s->nullinfo);
05502       
05503       sRefSet_free (s->deriv);
05504       s->deriv = sRefSet_undefined;
05505       sinfo_free (s);
05506       
05507       sfree (s); 
05508     }
05509 }
05510 
05511 void sRef_setType (sRef s, ctype t)
05512 {
05513   if (sRef_isValid (s))
05514     {
05515       s->type = t;
05516     }
05517 }
05518 
05519 void sRef_setTypeFull (sRef s, ctype t)
05520 {
05521   if (sRef_isValid (s))
05522     {
05523       s->type = t;
05524 
05525       sRefSet_allElements (s->deriv, current)
05526         {
05527           sRef_setTypeFull (current, ctype_unknown);
05528         } end_sRefSet_allElements ;
05529     }
05530 }
05531 
05532 /*@exposed@*/ sRef
05533   sRef_buildField (sRef rec, /*@dependent@*/ cstring f)
05534 {
05535   return (sRef_buildNCField (rec, f)); 
05536 }
05537 
05538 static /*@exposed@*/ sRef
05539 sRef_findDerivedField (/*@notnull@*/ sRef rec, cstring f)
05540 {
05541   sRefSet_allElements (rec->deriv, sr)
05542     {
05543       if (sRef_isValid (sr))
05544         {
05545           if (sr->kind == SK_FIELD && cstring_equal (sr->info->field->field, f))
05546             {
05547               return sr;
05548             }
05549         }
05550     } end_sRefSet_allElements;
05551 
05552   return sRef_undefined;
05553 }
05554 
05555 /*@dependent@*/ /*@observer@*/ sRefSet
05556   sRef_derivedFields (sRef rec)
05557 {
05558   if (sRef_isValid (rec))
05559     {
05560       sRefSet ret;
05561       ret = rec->deriv;
05562       return (ret);
05563     }
05564   else
05565     {
05566       return (sRefSet_undefined);
05567     }
05568 }
05569 
05570 static /*@exposed@*/ sRef
05571   sRef_findDerivedPointer (sRef s)
05572 {
05573   if (sRef_isValid (s))
05574     {
05575       sRefSet_realElements (s->deriv, sr)
05576         {
05577           if (sRef_isValid (sr) && sr->kind == SK_PTR)
05578             {
05579               return sr;
05580             }
05581         } end_sRefSet_realElements;
05582     }
05583 
05584   return sRef_undefined;
05585 }
05586 
05587 bool
05588 sRef_isUnknownArrayFetch (sRef s)
05589 {
05590   return (sRef_isValid (s) 
05591           && s->kind == SK_ARRAYFETCH
05592           && !s->info->arrayfetch->indknown);
05593 }
05594 
05595 static /*@exposed@*/ sRef
05596 sRef_findDerivedArrayFetch (/*@notnull@*/ sRef s, bool isknown, int idx, bool dead)
05597 {
05598   
05599   if (isknown) 
05600     {
05601       sRefSet_realElements (s->deriv, sr)
05602         {
05603           if (sRef_isValid (sr)
05604               && sr->kind == SK_ARRAYFETCH
05605               && sr->info->arrayfetch->indknown
05606               && (sr->info->arrayfetch->ind == idx))
05607             {
05608               return sr;
05609             }
05610         } end_sRefSet_realElements;
05611     }
05612   else
05613     {
05614       sRefSet_realElements (s->deriv, sr)
05615         {
05616           if (sRef_isValid (sr)
05617               && sr->kind == SK_ARRAYFETCH
05618               && (!sr->info->arrayfetch->indknown
05619                   || (sr->info->arrayfetch->indknown && 
05620                       sr->info->arrayfetch->ind == 0)))
05621             {
05622               if (sRef_isDead (sr) || sRef_isKept (sr))
05623                 {
05624                   if (dead || context_getFlag (FLG_STRICTUSERELEASED))
05625                     {
05626                       return sr;
05627                     }
05628                 }
05629               else
05630                 {
05631                   return sr;
05632                 }
05633             }
05634         } end_sRefSet_realElements;
05635     }
05636 
05637   return sRef_undefined;
05638 }
05639 
05640 static /*@exposed@*/ sRef 
05641 sRef_buildNCField (/*@exposed@*/ sRef rec, /*@exposed@*/ cstring f)
05642 {
05643   sRef s;
05644 
05645   if (sRef_isInvalid (rec))
05646     {
05647       return sRef_undefined;
05648     }
05649       
05650   /*
05651   ** check if the field already has been referenced 
05652   */
05653 
05654   s = sRef_findDerivedField (rec, f);
05655   
05656   if (sRef_isValid (s))
05657     {
05658             return s;
05659     }
05660   else
05661     {
05662       ctype ct = ctype_realType (rec->type);
05663 
05664       s = sRef_new ();      
05665       s->kind = SK_FIELD;
05666       s->info = (sinfo) dmalloc (sizeof (*s->info));
05667       s->info->field = (fldinfo) dmalloc (sizeof (*s->info->field));
05668       s->info->field->rec = rec;
05669       s->info->field->field = f; /* doesn't copy f */
05670       
05671       
05672       if (ctype_isKnown (ct) && ctype_isSU (ct))
05673         {
05674           uentry ue = uentryList_lookupField (ctype_getFields (ct), f);
05675         
05676           if (!uentry_isUndefined (ue))
05677             {
05678               s->type = uentry_getType (ue);
05679 
05680               if (ctype_isMutable (s->type)
05681                   && rec->aliaskind != AK_STACK 
05682                   && !alkind_isStatic (rec->aliaskind))
05683                 {
05684                   s->aliaskind = rec->aliaskind;
05685                 }
05686               else
05687                 {
05688                   s->aliaskind = AK_UNKNOWN;
05689                 }
05690 
05691               if (sRef_isStateDefined (rec) || sRef_isStateUnknown (rec) 
05692                   || sRef_isPdefined (rec))
05693                 {
05694                                   sRef_setStateFromUentry (s, ue);
05695                                 }
05696               else
05697                 {
05698                   sRef_setPartsFromUentry (s, ue);
05699                                 }
05700 
05701               s->oaliaskind = s->aliaskind;
05702               s->oexpkind = s->expkind;
05703             }
05704           else
05705             {
05706               /*
05707                 Never report this as an error.  It can happen whenever there
05708                 is casting involved.
05709 
05710               if (report)
05711                 {
05712                   llcontbug (message ("buildNCField --- no field %s: %q / %s",
05713                                       f, sRef_unparse (s), ctype_unparse (ct)));
05714                 }
05715                 */
05716 
05717               return sRef_undefined;
05718             }
05719         }
05720       
05721       if (rec->defstate == SS_DEFINED 
05722           && (s->defstate == SS_UNDEFINED || s->defstate == SS_UNKNOWN))
05723         {
05724           s->defstate = SS_DEFINED;
05725         }
05726       else if (rec->defstate == SS_PARTIAL)
05727         {
05728           s->defstate = SS_PARTIAL;
05729         }
05730       else if (rec->defstate == SS_ALLOCATED) 
05731         {
05732           if (ctype_isStackAllocated (ct) && ctype_isStackAllocated (s->type))
05733             {
05734               s->defstate = SS_ALLOCATED;
05735             }
05736           else
05737             {
05738               s->defstate = SS_UNDEFINED;
05739             }
05740         }
05741       else if (s->defstate == SS_UNKNOWN)
05742         {
05743           s->defstate = rec->defstate;
05744         }
05745       else
05746         {
05747           ; /* no change */
05748         }
05749 
05750       if (s->defstate == SS_UNDEFINED)
05751         {
05752           ctype rt = ctype_realType (s->type);
05753           
05754           if (ctype_isArray (rt) || ctype_isSU (rt))
05755             {
05756                       s->defstate = SS_ALLOCATED;
05757             }
05758         }
05759 
05760       sRef_addDeriv (rec, s);
05761 
05762       if (ctype_isInt (s->type) && cstring_equal (f, REFSNAME))
05763         {
05764           s->aliaskind = AK_REFS;
05765           s->oaliaskind = AK_REFS;
05766         }
05767 
05768             return s;
05769     }
05770 }
05771 
05772 bool
05773 sRef_isStackAllocated (sRef s)
05774 {
05775   return (sRef_isValid(s) 
05776           && s->defstate == SS_ALLOCATED && ctype_isStackAllocated (s->type));
05777 }
05778           
05779 static
05780 void sRef_setArrayFetchState (/*@notnull@*/ /*@exposed@*/ sRef s, 
05781                               /*@notnull@*/ /*@exposed@*/ sRef arr)
05782 {
05783   if (ctype_isRealAP (arr->type))
05784     {
05785       s->type = ctype_baseArrayPtr (arr->type);
05786     }
05787 
05788   /* a hack, methinks... makeArrayFetch (&a[0]) ==> a[] */
05789   if (sRef_isAddress (arr)) 
05790     {
05791       sRef t = arr->info->ref;
05792       
05793       if (sRef_isArrayFetch (t))
05794         {
05795           s->info->arrayfetch->arr = t->info->arrayfetch->arr;
05796         }
05797     }
05798   else if (ctype_isRealPointer (arr->type))
05799     {
05800       sRef sp = sRef_findDerivedPointer (arr);
05801 
05802       
05803       if (sRef_isValid (sp))
05804         {
05805           
05806           if (ctype_isMutable (s->type))
05807             {
05808               sRef_setExKind (s, sRef_getExKind (sp), fileloc_undefined);
05809 
05810                       
05811               s->aliaskind = sp->aliaskind;
05812             }
05813 
05814           s->defstate = sp->defstate;
05815 
05816           if (s->defstate == SS_DEFINED) 
05817             {
05818               if (!context_getFlag (FLG_STRICTDESTROY))
05819                 {
05820                   s->defstate = SS_PARTIAL;
05821                 }
05822             }
05823 
05824           s->nullstate = sp->nullstate;
05825         }
05826       else
05827         {
05828           if (arr->defstate == SS_UNDEFINED)
05829             {
05830               s->defstate = SS_UNUSEABLE;
05831             }
05832           else if ((arr->defstate == SS_ALLOCATED) && !ctype_isSU (s->type))
05833             {
05834               s->defstate = SS_UNDEFINED;
05835             }
05836           else
05837             {
05838               if (!context_getFlag (FLG_STRICTDESTROY))
05839                 {
05840                   s->defstate = SS_PARTIAL;
05841                 }
05842               else
05843                 {
05844                   s->defstate = SS_DEFINED;
05845                 }
05846 
05847               /*
05848               ** Very weak checking for array elements.
05849               ** Was:
05850               **     s->defstate = arr->defstate;
05851               */
05852             }
05853 
05854           sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
05855 
05856           if (arr->aliaskind == AK_LOCAL || arr->aliaskind == AK_FRESH)
05857             {
05858               s->aliaskind = AK_LOCAL;
05859             }
05860           else
05861             {
05862               s->aliaskind = AK_UNKNOWN;
05863             }
05864           
05865           sRef_setTypeState (s);
05866         }
05867     }
05868   else
05869     {
05870       if (arr->defstate == SS_DEFINED)
05871         {
05872           /*
05873           ** Very weak checking for array elements.
05874           ** Was:
05875           **     s->defstate = arr->defstate;
05876           */
05877 
05878           if (context_getFlag (FLG_STRICTDESTROY))
05879             {
05880               s->defstate = SS_DEFINED;
05881             }
05882           else
05883             {
05884               s->defstate = SS_PARTIAL;
05885             }
05886         }
05887       else if (arr->defstate == SS_ALLOCATED)
05888         {
05889           if (ctype_isRealArray (s->type))
05890             {
05891               s->defstate = SS_ALLOCATED;
05892             }
05893           else 
05894             {
05895               if (!s->info->arrayfetch->indknown)
05896                 {
05897                   /*
05898                   ** is index is unknown, elements is defined or 
05899                   ** allocated is any element is!
05900                   */
05901                   
05902                   s->defstate = SS_UNDEFINED;
05903                   
05904                   sRefSet_allElements (arr->deriv, sr)
05905                     {
05906                       if (sRef_isValid (sr))
05907                         {
05908                           if (sr->defstate == SS_ALLOCATED)
05909                             {
05910                               s->defstate = SS_ALLOCATED;
05911                             }
05912                           else 
05913                             {
05914                               if (sr->defstate == SS_DEFINED)
05915                                 {
05916                                   if (context_getFlag (FLG_STRICTDESTROY))
05917                                     {
05918                                       s->defstate = SS_DEFINED;
05919                                     }
05920                                   else
05921                                     {
05922                                       s->defstate = SS_PARTIAL;
05923                                     }
05924 
05925                                   break;
05926                                 }
05927                             }
05928                         }
05929                     } end_sRefSet_allElements;
05930                   
05931                                 }
05932               else
05933                 {
05934                   s->defstate = SS_UNDEFINED;
05935                 }
05936             }
05937         }
05938       else
05939         {
05940           s->defstate = arr->defstate;
05941         }
05942       
05943       
05944       /*
05945       ** kludgey way to guess where aliaskind applies
05946       */
05947       
05948       if (ctype_isMutable (s->type) 
05949           && !ctype_isPointer (arr->type) 
05950           && !alkind_isStatic (arr->aliaskind)
05951           && !alkind_isStack (arr->aliaskind)) /* evs - 2000-06-20: don't pass stack allocation to members */
05952         {
05953           s->aliaskind = arr->aliaskind;
05954         }
05955       else
05956         {
05957           s->aliaskind = AK_UNKNOWN;
05958         }
05959     
05960       sRef_setTypeState (s);
05961     }
05962 
05963   if (sRef_isObserver (arr)) 
05964     {
05965       s->expkind = XO_OBSERVER;
05966     }
05967 }  
05968 
05969 /*@exposed@*/ sRef sRef_buildArrayFetch (/*@exposed@*/ sRef arr)
05970 {
05971   sRef s;
05972 
05973   if (!sRef_isValid (arr)) {
05974     /*@-nullret@*/ return arr /*@=nullret@*/;
05975   }
05976 
05977   if (ctype_isRealPointer (arr->type))
05978     {
05979       (void) sRef_buildPointer (arr); /* do this to define arr! */
05980     }
05981   
05982   s = sRef_findDerivedArrayFetch (arr, FALSE, 0, FALSE);
05983   
05984   if (sRef_isValid (s))
05985     {
05986       sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);
05987       return s;
05988     }
05989   else
05990     {
05991       s = sRef_new ();
05992 
05993       s->kind = SK_ARRAYFETCH;
05994       s->info = (sinfo) dmalloc (sizeof (*s->info));
05995       s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
05996       s->info->arrayfetch->indknown = FALSE;
05997       s->info->arrayfetch->ind = 0;
05998       s->info->arrayfetch->arr = arr;
05999       sRef_setArrayFetchState (s, arr);
06000       s->oaliaskind = s->aliaskind;
06001       s->oexpkind = s->expkind;
06002 
06003       if (!context_inProtectVars ())
06004         {
06005           sRef_addDeriv (arr, s);
06006         }
06007       
06008       return (s);
06009     }
06010 }
06011 
06012 /*@exposed@*/ sRef
06013   sRef_buildArrayFetchKnown (/*@exposed@*/ sRef arr, int i)
06014 {
06015   sRef s;
06016 
06017   if (!sRef_isValid (arr)) {
06018     /*@-nullret@*/ return arr /*@=nullret@*/;
06019   }
06020 
06021   if (ctype_isRealPointer (arr->type))
06022     {
06023        (void) sRef_buildPointer (arr); /* do this to define arr! */
06024     }
06025 
06026   s = sRef_findDerivedArrayFetch (arr, TRUE, i, FALSE);
06027       
06028   if (sRef_isValid (s))
06029     {
06030       sRef_setExKind (s, sRef_getExKind (arr), g_currentloc);      
06031       return s;
06032     }
06033   else
06034     {
06035       s = sRef_new ();
06036       
06037       s->kind = SK_ARRAYFETCH;
06038       s->info = (sinfo) dmalloc (sizeof (*s->info));
06039       s->info->arrayfetch = (ainfo) dmalloc (sizeof (*s->info->arrayfetch));
06040       s->info->arrayfetch->arr = arr;
06041       s->info->arrayfetch->indknown = TRUE;
06042       s->info->arrayfetch->ind = i;
06043       
06044       sRef_setArrayFetchState (s, arr);
06045       
06046       s->oaliaskind = s->aliaskind;
06047       s->oexpkind = s->expkind;
06048       sRef_addDeriv (arr, s);
06049 
06050       return (s);
06051     }
06052 }
06053 
06054 /*
06055 ** sets everything except for defstate
06056 */
06057 
06058 static void
06059 sRef_setPartsFromUentry (sRef s, uentry ue)
06060 {
06061     
06062   llassert (sRef_isValid (s));
06063 
06064   s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
06065   s->oaliaskind = s->aliaskind;
06066 
06067   if (s->expkind == XO_UNKNOWN)
06068     {
06069       s->expkind = uentry_getExpKind (ue);
06070     }
06071 
06072   s->oexpkind = s->expkind;
06073 
06074   if (s->nullstate == NS_UNKNOWN)
06075     {
06076       s->nullstate = sRef_getNullState (uentry_getSref (ue));
06077     }
06078 
06079   if (s->aliaskind == AK_IMPONLY 
06080       && (sRef_isExposed (s) || sRef_isObserver (s)))
06081     {
06082       s->oaliaskind = s->aliaskind = AK_IMPDEPENDENT;
06083     }
06084 
06085 }
06086 
06087 static void
06088 sRef_setStateFromAbstractUentry (sRef s, uentry ue)
06089 {
06090   llassert (sRef_isValid (s));
06091   
06092   sRef_setPartsFromUentry (s, ue);
06093 
06094   s->aliaskind = alkind_derive (s->aliaskind, uentry_getAliasKind (ue));
06095   s->oaliaskind = s->aliaskind;
06096 
06097   if (s->expkind == XO_UNKNOWN)
06098     {
06099       s->expkind = uentry_getExpKind (ue);
06100     }
06101 
06102   s->oexpkind = s->expkind;
06103 }
06104 
06105 void
06106 sRef_setStateFromUentry (sRef s, uentry ue)
06107 {
06108   sstate defstate;
06109 
06110   llassert (sRef_isValid (s));
06111   
06112   sRef_setPartsFromUentry (s, ue);
06113 
06114   defstate = uentry_getDefState (ue);
06115 
06116   if (sstate_isKnown (defstate))
06117     {
06118       s->defstate = defstate;
06119     }
06120   else
06121     {
06122       ;
06123     }
06124 }
06125 
06126 /*@exposed@*/ sRef
06127   sRef_buildPointer (/*@exposed@*/ sRef t)
06128 {
06129   DPRINTF (("build pointer: %s", sRef_unparse (t)));
06130 
06131   if (sRef_isInvalid (t)) return sRef_undefined;
06132 
06133   if (sRef_isAddress (t))
06134     {
06135       DPRINTF (("Return ref: %s", sRef_unparse (t->info->ref)));
06136       return (t->info->ref);
06137     }
06138   else
06139     {
06140       sRef s = sRef_findDerivedPointer (t);
06141 
06142       DPRINTF (("find derived: %s", sRef_unparse (s)));
06143 
06144       if (sRef_isValid (s))
06145         {
06146           
06147           sRef_setExKind (s, sRef_getExKind (t), g_currentloc);
06148           s->oaliaskind = s->aliaskind;
06149           s->oexpkind = s->expkind;
06150 
06151           return s;
06152         }
06153       else
06154         {
06155           s = sRef_constructPointerAux (t);
06156           
06157           DPRINTF (("construct: %s", sRef_unparse (s)));
06158 
06159           if (sRef_isValid (s))
06160             {
06161               sRef_addDeriv (t, s);
06162 
06163               s->oaliaskind = s->aliaskind;
06164               s->oexpkind = s->expkind;
06165             }
06166           
06167           return s;
06168         }
06169     }
06170 }
06171 
06172 /*@exposed@*/ sRef
06173 sRef_constructPointer (sRef t)
06174    /*@modifies t@*/
06175 {
06176   return sRef_buildPointer (t);
06177 }
06178 
06179 static /*@exposed@*/ sRef sRef_constructDerefAux (sRef t, bool isdead)
06180 {
06181   if (sRef_isValid (t))
06182     {
06183       sRef s;
06184       
06185       /*
06186       ** if there is a derived t[?], return that.  Otherwise, *t.
06187       */
06188       
06189             
06190       s = sRef_findDerivedArrayFetch (t, FALSE, 0, isdead);
06191       
06192       if (sRef_isValid (s))
06193         {
06194                   return s;
06195         }
06196       else
06197         {
06198           sRef ret = sRef_constructPointer (t);
06199 
06200           /*
06201           ** This is necessary to prevent infinite depth
06202           ** in checking complete destruction.  
06203           */
06204 
06205           
06206           if (isdead)
06207             {
06208               /* ret->defstate = SS_UNKNOWN;  */
06209               return ret; 
06210             }
06211           else
06212             {
06213               return ret;
06214             }
06215         }
06216     }
06217   else
06218     {
06219       return sRef_undefined;
06220     }
06221 }
06222 
06223 sRef sRef_constructDeref (sRef t)
06224 {
06225   return sRef_constructDerefAux (t, FALSE);
06226 }
06227 
06228 sRef sRef_constructDeadDeref (sRef t)
06229 {
06230   return sRef_constructDerefAux (t, TRUE);
06231 }
06232 
06233 static sRef
06234 sRef_constructPointerAux (/*@notnull@*/ /*@exposed@*/ sRef t)
06235 {
06236   sRef s = sRef_new ();
06237   ctype rt = t->type;
06238   ctype st;
06239   
06240   s->kind = SK_PTR;
06241   s->info = (sinfo) dmalloc (sizeof (*s->info));
06242   s->info->ref = t;
06243   
06244   if (ctype_isRealAP (rt))
06245     {
06246       s->type = ctype_baseArrayPtr (rt);
06247     }
06248   
06249   st = ctype_realType (s->type);
06250   
06251     
06252   if (t->defstate == SS_UNDEFINED)
06253     {
06254       s->defstate = SS_UNUSEABLE;
06255     }
06256   else if ((t->defstate == SS_ALLOCATED) && !ctype_isSU (st))
06257     {
06258       s->defstate = SS_UNDEFINED;
06259     }
06260   else
06261     {
06262       s->defstate = t->defstate;
06263     }
06264   
06265   if (t->aliaskind == AK_LOCAL || t->aliaskind == AK_FRESH)
06266     {
06267       s->aliaskind = AK_LOCAL;
06268     }
06269   else
06270     {
06271       s->aliaskind = AK_UNKNOWN;
06272     }
06273   
06274   sRef_setExKind (s, sRef_getExKind (t), fileloc_undefined);
06275   sRef_setTypeState (s);
06276   
06277   s->oaliaskind = s->aliaskind;
06278   s->oexpkind = s->expkind;
06279 
06280   return s;
06281 }
06282 
06283 bool sRef_hasDerived (sRef s)
06284 {
06285   return (sRef_isValid (s) && !sRefSet_isEmpty (s->deriv));
06286 }
06287 
06288 void
06289 sRef_clearDerived (sRef s)
06290 {
06291   if (sRef_isValid (s))
06292     {
06293             sRefSet_clear (s->deriv); 
06294     }
06295 }
06296 
06297 void
06298 sRef_clearDerivedComplete (sRef s)
06299 {
06300   
06301   if (sRef_isValid (s))
06302     {
06303       sRef base = sRef_getBaseSafe (s);
06304 
06305       while (sRef_isValid (base))
06306         {
06307           sRefSet_clear (base->deriv); 
06308           base = sRef_getBaseSafe (base);
06309         }
06310 
06311       sRefSet_clear (s->deriv); 
06312     }
06313 }
06314 
06315 /*@exposed@*/ sRef
06316 sRef_makePointer (sRef s)
06317    /*@modifies s@*/
06318 {
06319   sRef res = sRef_buildPointer (s); 
06320 
06321   DPRINTF (("Res: %s", sRef_unparse (res)));
06322   return res;
06323 }
06324 
06325 /*
06326 ** &a[] => a (this is for out params)
06327 */
06328 
06329 /*@exposed@*/ sRef
06330 sRef_makeAnyArrayFetch (/*@exposed@*/ sRef arr)
06331 {
06332   
06333   if (sRef_isAddress (arr))
06334     {
06335             return (arr->info->ref);
06336     }
06337   else
06338     {
06339       return (sRef_buildArrayFetch (arr));
06340     }
06341 }
06342 
06343 /*@exposed@*/ sRef
06344 sRef_makeArrayFetch (sRef arr)
06345 {
06346   return (sRef_buildArrayFetch (arr));
06347 }
06348 
06349 /*@exposed@*/ sRef
06350 sRef_makeArrayFetchKnown (sRef arr, int i)
06351 {
06352   return (sRef_buildArrayFetchKnown (arr, i));
06353 }
06354 
06355 /*@exposed@*/ sRef
06356 sRef_makeField (sRef rec, /*@dependent@*/ cstring f)
06357 {
06358   sRef ret;
06359   ret = sRef_buildField (rec, f);
06360   return ret;
06361 }
06362 
06363 /*@exposed@*/ sRef
06364 sRef_makeNCField (sRef rec, /*@dependent@*/ cstring f)
06365 {
06366     return (sRef_buildNCField (rec, f));
06367 }
06368 
06369 /*@only@*/ cstring
06370 sRef_unparseKindName (sRef s)
06371 {
06372   cstring result;
06373 
06374   if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
06375 
06376   s = sRef_fixConj (s);
06377 
06378   switch (s->kind)
06379     {
06380     case SK_CVAR: 
06381       if (sRef_isLocalVar (s)) 
06382         {
06383           result = cstring_makeLiteral ("Variable");
06384         }
06385       else
06386         {
06387           result = cstring_makeLiteral ("Undef global");
06388         }
06389       break;
06390     case SK_PARAM:
06391       result = cstring_makeLiteral ("Out parameter");
06392       break;
06393     case SK_ARRAYFETCH:
06394       if (sRef_isAnyParam (s->info->arrayfetch->arr)) 
06395         {
06396           result = cstring_makeLiteral ("Out parameter");
06397         }
06398       else if (sRef_isIndexKnown (s))
06399         {
06400           result = cstring_makeLiteral ("Array element");
06401         }
06402       else
06403         {
06404           result = cstring_makeLiteral ("Value");
06405         }
06406       break;
06407     case SK_PTR:
06408       if (sRef_isAnyParam (s->info->ref)) 
06409         {
06410           result = cstring_makeLiteral ("Out parameter");
06411         }
06412       else
06413         {
06414           result = cstring_makeLiteral ("Value");
06415         }
06416       break;
06417     case SK_ADR:
06418       result = cstring_makeLiteral ("Value");
06419       break;
06420     case SK_FIELD:
06421       result = cstring_makeLiteral ("Field");
06422       break;
06423     case SK_OBJECT:
06424       result = cstring_makeLiteral ("Object");
06425       break;
06426     case SK_UNCONSTRAINED:
06427       result = cstring_makeLiteral ("<anything>");
06428       break;
06429     case SK_RESULT:
06430     case SK_SPECIAL:
06431     case SK_UNKNOWN:
06432     case SK_EXTERNAL:
06433     case SK_DERIVED:
06434     case SK_CONST:
06435     case SK_TYPE:
06436       result = cstring_makeLiteral ("<unknown>");
06437       break;
06438     case SK_CONJ:
06439       result = cstring_makeLiteral ("<conj>");
06440       break;
06441     case SK_NEW:
06442       result = cstring_makeLiteral ("Storage");
06443       break;
06444     }
06445   
06446   return result;
06447 }
06448 
06449 /*@only@*/ cstring
06450 sRef_unparseKindNamePlain (sRef s)
06451 {
06452   cstring result;
06453 
06454   if (s == sRef_undefined) return cstring_makeLiteral ("<invalid>");
06455 
06456   s = sRef_fixConj (s);
06457 
06458   switch (s->kind)
06459     {
06460     case SK_CVAR: 
06461       if (sRef_isLocalVar (s)) 
06462         {
06463           result = cstring_makeLiteral ("Variable");
06464         }
06465       else 
06466         {
06467           result = cstring_makeLiteral ("Global");
06468         }
06469       break;
06470     case SK_PARAM:
06471       result = cstring_makeLiteral ("Parameter");
06472       break;
06473     case SK_ARRAYFETCH:
06474       if (sRef_isAnyParam (s->info->arrayfetch->arr)) 
06475         {
06476           result = cstring_makeLiteral ("Parameter");
06477         }
06478       else if (sRef_isIndexKnown (s))
06479         {
06480           result = cstring_makeLiteral ("Array element");
06481         }
06482       else 
06483         {
06484           result = cstring_makeLiteral ("Value");
06485         }
06486       break;
06487     case SK_PTR:
06488       if (sRef_isAnyParam (s->info->ref))
06489         {
06490           result = cstring_makeLiteral ("Parameter");
06491         }
06492       else
06493         {
06494           result = cstring_makeLiteral ("Value");
06495         }
06496       break;
06497     case SK_ADR:
06498       result = cstring_makeLiteral ("Value");
06499       break;
06500     case SK_FIELD:
06501       result = cstring_makeLiteral ("Field");
06502       break;
06503     case SK_OBJECT:
06504       result = cstring_makeLiteral ("Object");
06505       break;
06506     case SK_NEW:
06507       result = cstring_makeLiteral ("Storage");
06508       break;
06509     case SK_UNCONSTRAINED:
06510       result = cstring_makeLiteral ("<anything>");
06511       break;
06512     case SK_RESULT:
06513     case SK_TYPE:
06514     case SK_CONST:
06515     case SK_EXTERNAL:
06516     case SK_DERIVED:
06517     case SK_UNKNOWN:
06518     case SK_SPECIAL:
06519       result = cstring_makeLiteral ("<unknown>");
06520       break;
06521     case SK_CONJ:
06522       result = cstring_makeLiteral ("<conj>");
06523       break;
06524     }
06525   
06526   return result;
06527 }
06528 
06529 /*
06530 ** s1 <- s2
06531 */
06532 
06533 void
06534 sRef_copyState (sRef s1, sRef s2)
06535 {
06536   if (sRef_isValid (s1) && sRef_isValid (s2))
06537     {
06538       s1->defstate = s2->defstate;
06539       
06540       s1->nullstate = s2->nullstate;
06541       s1->nullinfo = alinfo_update (s1->nullinfo, s2->nullinfo);
06542 
06543       s1->aliaskind = s2->aliaskind;
06544       s1->aliasinfo = alinfo_update (s1->aliasinfo, s2->aliasinfo);
06545 
06546       s1->expkind = s2->expkind;
06547       s1->expinfo = alinfo_update (s1->expinfo, s2->expinfo);
06548 
06549       s1->safe = s2->safe;
06550           }
06551 }
06552 
06553 sRef
06554 sRef_makeNew (ctype ct, sRef t, cstring name)
06555 {
06556   sRef s = sRef_new ();
06557 
06558   s->kind = SK_NEW;
06559   s->type = ct;
06560 
06561   llassert (sRef_isValid (t));
06562   s->defstate = t->defstate;
06563 
06564   s->aliaskind = t->aliaskind;
06565   s->oaliaskind = s->aliaskind;
06566 
06567   s->nullstate = t->nullstate;
06568 
06569   s->expkind = t->expkind;
06570   s->oexpkind = s->expkind;
06571 
06572   s->info = (sinfo) dmalloc (sizeof (*s->info));
06573   s->info->fname = name;
06574 
06575     return s;
06576 }
06577 
06578 sRef
06579 sRef_makeType (ctype ct)
06580 {
06581   sRef s = sRef_new ();
06582   
06583   s->kind = SK_TYPE;
06584   s->type = ct;
06585 
06586   s->defstate = SS_UNKNOWN; 
06587   s->aliaskind = AK_UNKNOWN;
06588   s->nullstate = NS_UNKNOWN;
06589 
06590     
06591   if (ctype_isUA (ct))
06592     {
06593       typeId uid = ctype_typeId (ct);
06594       uentry ue = usymtab_getTypeEntrySafe (uid);
06595 
06596       if (uentry_isValid (ue))
06597         {
06598           sRef_mergeStateQuiet (s, uentry_getSref (ue));
06599         }
06600     }
06601 
06602     s->oaliaskind = s->aliaskind;
06603   s->oexpkind = s->expkind;
06604 
06605   return s;
06606 }
06607 
06608 sRef
06609 sRef_makeConst (ctype ct)
06610 {
06611   sRef s = sRef_new ();
06612   
06613   s->kind = SK_CONST;
06614   s->type = ct;
06615 
06616   s->defstate = SS_UNKNOWN;
06617   s->aliaskind = AK_UNKNOWN;
06618   s->nullstate = NS_UNKNOWN;
06619 
06620   
06621   if (ctype_isUA (ct))
06622     {
06623       typeId uid = ctype_typeId (ct);
06624       uentry te = usymtab_getTypeEntrySafe (uid);
06625       
06626       if (uentry_isValid (te))
06627         {
06628           sRef_mergeStateQuiet (s, uentry_getSref (te));
06629         }
06630     }
06631 
06632   
06633   s->oaliaskind = s->aliaskind;
06634   s->oexpkind = s->expkind;
06635 
06636   return s;
06637 }
06638 
06639 bool sRef_hasName (sRef s)
06640 {
06641   if (sRef_isInvalid (s))
06642     {
06643       return (FALSE);
06644     }
06645 
06646   switch (s->kind)
06647     {
06648     case SK_CVAR:
06649       {
06650         uentry u = usymtab_getRefQuiet (s->info->cvar->lexlevel,
06651                                          s->info->cvar->index);
06652         return (uentry_hasName (u));
06653       }
06654     case SK_PARAM:
06655       {
06656         uentry u = uentryList_getN (context_getParams (), 
06657                                     s->info->paramno);
06658 
06659         return (uentry_hasName (u));
06660       }
06661     default:
06662       return TRUE;
06663     }
06664 }
06665 
06666 bool
06667 sRef_sameName (sRef s1, sRef s2)
06668 {
06669   if (sRef_isInvalid (s1))
06670     {
06671       return sRef_isInvalid (s2);
06672     }
06673 
06674   if (sRef_isInvalid (s2))
06675     {
06676       return (FALSE);
06677     }
06678 
06679   switch (s1->kind)
06680     {
06681     case SK_CVAR:
06682       if (s2->kind == SK_CVAR)
06683         {
06684           return (s1->info->cvar->lexlevel == s2->info->cvar->lexlevel
06685                   && s1->info->cvar->index == s2->info->cvar->index);
06686         }
06687       else if (s2->kind == SK_PARAM)
06688         {
06689           if (context_inFunctionLike ())
06690             {
06691               uentry u1 = usymtab_getRefQuiet (s1->info->cvar->lexlevel,
06692                                                s1->info->cvar->index);
06693               uentry u2 = uentryList_getN (context_getParams (), 
06694                                            s2->info->paramno);
06695           
06696               return (cstring_equalFree (uentry_getName (u1),
06697                                          uentry_getName (u2)));
06698             }
06699           else 
06700             {
06701               return FALSE;
06702             }
06703         }
06704       else
06705         {
06706           return FALSE;
06707         }
06708     case SK_PARAM:
06709       {
06710         if (s2->kind == SK_PARAM)
06711           {
06712             return (s1->info->paramno == s2->info->paramno);
06713           }
06714         else if (s2->kind == SK_CVAR)
06715           {
06716             if (context_inFunctionLike ())
06717               {
06718                 uentry u1 = uentryList_getN (context_getParams (), 
06719                                              s1->info->paramno);
06720                 uentry u2 = usymtab_getRefQuiet (s2->info->cvar->lexlevel,
06721                                                  s2->info->cvar->index);
06722 
06723                 
06724                 return (cstring_equalFree (uentry_getName (u1),
06725                                            uentry_getName (u2)));
06726               }
06727             else 
06728               {
06729                 return FALSE;
06730               }
06731           }
06732         else
06733           {
06734             return FALSE;
06735           }
06736       }
06737 
06738     case SK_UNCONSTRAINED:
06739       return FALSE;
06740 
06741     case SK_ARRAYFETCH:
06742       if (s2->kind == SK_ARRAYFETCH)
06743         {
06744           if (bool_equal (s1->info->arrayfetch->indknown,
06745                           s2->info->arrayfetch->indknown))
06746             {
06747               if (!s1->info->arrayfetch->indknown 
06748                   || (s1->info->arrayfetch->ind == s2->info->arrayfetch->ind))
06749                 {
06750                   return sRef_sameName (s1->info->arrayfetch->arr,
06751                                         s2->info->arrayfetch->arr);
06752                 }
06753             }
06754         }
06755 
06756       return FALSE;
06757     case SK_FIELD:
06758       if (s2->kind == SK_FIELD)
06759         {
06760           if (cstring_equal (s1->info->field->field,
06761                              s2->info->field->field))
06762             {
06763               return sRef_sameName (s1->info->field->rec,
06764                                     s2->info->field->rec);
06765             }
06766 
06767         }
06768       return FALSE;
06769     case SK_PTR:
06770     case SK_ADR:
06771     case SK_DERIVED:
06772     case SK_EXTERNAL:
06773       if (s2->kind == s1->kind)
06774         {
06775           return sRef_sameName (s1->info->ref,
06776                                 s2->info->ref);
06777         }
06778 
06779       return FALSE;
06780     case SK_OBJECT:
06781       return FALSE;
06782     case SK_CONJ:
06783       return sRef_sameName (sRef_getConjA (s1), s2);
06784     case SK_NEW:
06785       return FALSE;
06786     case SK_UNKNOWN:
06787       return (s2->kind == SK_UNKNOWN);
06788     case SK_TYPE:
06789     case SK_CONST:
06790       if (s2->kind == s1->kind)
06791         {
06792           return (ctype_equal (s1->type, s2->type));
06793         }
06794       
06795       return FALSE;
06796     case SK_SPECIAL:
06797       if (s2->kind == SK_SPECIAL)
06798         {
06799           return (s1->info->spec == s2->info->spec);
06800         }
06801       return FALSE;
06802     case SK_RESULT:
06803       return (s2->kind == SK_RESULT);
06804     default:
06805       return FALSE;
06806     }
06807   BADEXIT;
06808 }
06809                 
06810 sRef
06811 sRef_fixOuterRef (/*@returned@*/ sRef s)
06812 {
06813   sRef root = sRef_getRootBase (s);
06814 
06815   if (sRef_isCvar (root))
06816     {
06817       uentry ue = usymtab_getRefQuiet (root->info->cvar->lexlevel, 
06818                                        root->info->cvar->index);
06819 
06820       if (uentry_isValid (ue))
06821         {
06822           sRef uref = uentry_getSref (ue);
06823           sRef sr = sRef_fixBase (s, uref);
06824 
06825           return (sr);
06826         }
06827       else
06828         {
06829           llcontbug (message ("sRef_fixOuterRef: undefined: %q", sRef_unparseDebug (s)));
06830           return (s);
06831         }
06832     }
06833 
06834   return (s);
06835 }
06836 
06837 void
06838 sRef_storeState (sRef s)
06839 {
06840   if (sRef_isInvalid (s)) return;
06841 
06842   s->oaliaskind = s->aliaskind;
06843   s->oexpkind = s->expkind;
06844 }
06845   
06846 static void sRef_resetStateAux (sRef s, /*@unused@*/ fileloc loc)
06847 {
06848   sRef_resetState (s);
06849 }
06850 
06851 void
06852 sRef_resetState (sRef s)
06853 {
06854   bool changed = FALSE;
06855   if (sRef_isInvalid (s)) return;
06856 
06857   
06858   if (s->oaliaskind == AK_KILLREF && !sRef_isParam (s))
06859     {
06860       /*
06861       ** killref is used in a kludgey way, to save having to add
06862       ** another alias kind (see usymtab_handleParams)
06863       */
06864  
06865       if (s->expkind != s->oexpkind)
06866         {
06867           changed = TRUE;
06868           s->expkind = s->oexpkind;
06869         }
06870     }
06871   else
06872     {
06873       if (s->expkind != s->oexpkind)
06874         {
06875           changed = TRUE;
06876           s->expkind = s->oexpkind;       
06877         }
06878 
06879       if (s->aliaskind != s->oaliaskind
06880           && s->aliaskind != AK_REFCOUNTED
06881           && s->aliaskind != AK_REFS)
06882         {
06883           changed = TRUE;
06884           s->aliaskind = s->oaliaskind;
06885                 }
06886     }
06887 
06888   if (changed)
06889     {
06890       sRef_clearDerived (s);
06891     }
06892   
06893   }
06894 
06895 void
06896 sRef_resetStateComplete (sRef s)
06897 {
06898   sRef_innerAliasSetComplete (sRef_resetStateAux, s, fileloc_undefined);
06899 }
06900 
06901 /*@exposed@*/ sRef
06902 sRef_fixBase (/*@returned@*/ sRef s, /*@returned@*/ sRef base)
06903 {
06904   sRef tmp = sRef_undefined;
06905   sRef ret;
06906 
06907   if (sRef_isInvalid (s)) return s;
06908   if (sRef_isInvalid (base)) return base;
06909 
06910   switch (s->kind)
06911     {
06912     case SK_RESULT:
06913     case SK_PARAM:
06914     case SK_CVAR:
06915       ret = base;
06916       break;
06917     case SK_ARRAYFETCH:
06918       tmp = sRef_fixBase (s->info->arrayfetch->arr, base);
06919 
06920       if (s->info->arrayfetch->indknown)
06921         {
06922           ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
06923         }
06924       else
06925         {
06926           ret = sRef_makeArrayFetch (tmp);
06927         }
06928       break;
06929     case SK_FIELD:
06930       tmp = sRef_fixBase (s->info->field->rec, base);
06931       ret = sRef_buildNCField (tmp, s->info->field->field);
06932       break;
06933     case SK_PTR:
06934       tmp = sRef_fixBase (s->info->ref, base);
06935       ret = sRef_makePointer (tmp);
06936       break;
06937     case SK_ADR:
06938       tmp = sRef_fixBase (s->info->ref, base);
06939       ret = sRef_makeAddress (tmp);
06940       break;
06941     case SK_CONJ:
06942       {
06943         sRef tmpb;
06944 
06945         tmp = sRef_fixBase (s->info->conj->a, base);
06946         tmpb = sRef_fixBase (s->info->conj->b, base);
06947 
06948         ret = sRef_makeConj (tmp, tmpb);
06949         break;
06950       }
06951       BADDEFAULT;
06952     }
06953 
06954   return ret;
06955 }
06956 
06957 static /*@exposed@*/ sRef 
06958 sRef_fixDirectBase (sRef s, sRef base)
06959 {
06960   sRef ret;
06961 
06962   
06963   if (sRef_isInvalid (s))
06964     {
06965             return sRef_undefined;
06966     }
06967 
06968   switch (s->kind)
06969     {
06970     case SK_ARRAYFETCH:
06971       if (s->info->arrayfetch->indknown)
06972         {
06973           ret = sRef_makeArrayFetchKnown (base, s->info->arrayfetch->ind);
06974         }
06975       else
06976         {
06977           ret = sRef_makeArrayFetch (base);
06978         }
06979       break;
06980     case SK_FIELD:
06981       ret = sRef_buildNCField (base, s->info->field->field);
06982       break;
06983     case SK_PTR:
06984             ret = sRef_makePointer (base);
06985             break;
06986     case SK_ADR:
06987       ret = sRef_makeAddress (base);
06988       break;
06989     case SK_CONJ:
06990       {
06991         sRef tmpa, tmpb;
06992 
06993         tmpa = sRef_fixDirectBase (s->info->conj->a, base);
06994         tmpb = sRef_fixDirectBase (s->info->conj->b, base);
06995 
06996         ret = sRef_makeConj (tmpa, tmpb);
06997         break;
06998       }
06999       BADDEFAULT;
07000     }
07001 
07002     sRef_copyState (ret, s);
07003     return ret;
07004 }
07005 
07006 bool
07007 sRef_isAllocIndexRef (sRef s)
07008 {
07009   return (sRef_isArrayFetch (s) && !(s->info->arrayfetch->indknown) 
07010           && sRef_isAllocated (s->info->arrayfetch->arr));
07011 }
07012 
07013 void
07014 sRef_showRefLost (sRef s)
07015 {
07016   if (sRef_hasAliasInfoLoc (s))
07017     {
07018       llgenindentmsg (cstring_makeLiteral ("Original reference lost"),
07019                 sRef_getAliasInfoLoc (s));
07020     }
07021 }
07022 
07023 void
07024 sRef_showRefKilled (sRef s)
07025 {
07026   if (sRef_hasStateInfoLoc (s))
07027     {
07028       llgenindentmsg (message ("Storage %q released", 
07029                                sRef_unparse (s)), sRef_getStateInfoLoc (s));
07030     }
07031 }
07032 
07033 void
07034 sRef_showStateInconsistent (sRef s)
07035 {
07036   if (sRef_hasStateInfoLoc (s))
07037     {
07038       llgenindentmsg
07039         (message ("Storage %qbecomes inconsistent (released on one branch)",
07040                   sRef_unparseOpt (s)), 
07041          sRef_getStateInfoLoc (s));
07042     }
07043 }
07044 
07045 void
07046 sRef_showStateInfo (sRef s)
07047 {
07048   if (sRef_hasStateInfoLoc (s))
07049     {
07050       if (s->defstate == SS_DEAD)
07051         {
07052           llgenindentmsg 
07053             (message ("Storage %qis released", sRef_unparseOpt (s)),
07054              sRef_getStateInfoLoc (s));
07055         }
07056       else if (s->defstate == SS_ALLOCATED || s->defstate == SS_DEFINED)
07057         {
07058           llgenindentmsg 
07059             (message ("Storage %qis %s", sRef_unparseOpt (s), 
07060                       sstate_unparse (s->defstate)),
07061              sRef_getStateInfoLoc (s));
07062         }
07063       else if (s->defstate == SS_UNUSEABLE)
07064         {
07065           llgenindentmsg 
07066             (message ("Storage %qbecomes inconsistent (clauses merge with"
07067                       "%qreleased on one branch)",
07068                       sRef_unparseOpt (s), 
07069                       sRef_unparseOpt (s)),
07070              sRef_getStateInfoLoc (s));
07071         }
07072       else 
07073         {
07074           llgenindentmsg (message ("Storage %qbecomes %s", 
07075                                    sRef_unparseOpt (s), 
07076                                    sstate_unparse (s->defstate)),
07077                           sRef_getStateInfoLoc (s));
07078         }
07079     }
07080 }
07081 
07082 void
07083 sRef_showExpInfo (sRef s)
07084 {
07085   if (sRef_hasExpInfoLoc (s))
07086     {
07087       llgenindentmsg (message ("Storage %qbecomes %s", sRef_unparseOpt (s), 
07088                                exkind_unparse (s->expkind)),
07089                       sRef_getExpInfoLoc (s));
07090     }
07091 }
07092 
07093 void
07094 sRef_showNullInfo (sRef s)
07095 {
07096   if (sRef_hasNullInfoLoc (s) && sRef_isKnown (s))
07097     {
07098       switch (s->nullstate)
07099         {
07100         case NS_CONSTNULL:
07101           {
07102             fileloc loc = sRef_getNullInfoLoc (s);
07103             
07104             if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
07105               {
07106                 llgenindentmsg 
07107                   (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
07108                    loc);
07109               }
07110             break;
07111           }
07112         case NS_DEFNULL:
07113           {
07114             fileloc loc = sRef_getNullInfoLoc (s);
07115             
07116             if (fileloc_isDefined (loc) && !fileloc_isLib (loc))
07117               {
07118                 llgenindentmsg (message ("Storage %qbecomes null", sRef_unparseOpt (s)),
07119                                 loc);
07120               }
07121             break;
07122           }
07123         case NS_ABSNULL:
07124         case NS_POSNULL:
07125           llgenindentmsg
07126             (message ("Storage %qmay become null", sRef_unparseOpt (s)),
07127              sRef_getNullInfoLoc (s));
07128           break;
07129         case NS_NOTNULL:
07130         case NS_MNOTNULL:
07131           llgenindentmsg
07132             (message ("Storage %qbecomes not null", sRef_unparseOpt (s)),
07133              sRef_getNullInfoLoc (s));
07134           break;
07135         case NS_UNKNOWN:
07136           llgenindentmsg
07137             (message ("Storage %qnull state becomes unknown",
07138                       sRef_unparseOpt (s)),
07139              sRef_getNullInfoLoc (s));
07140           break;
07141 
07142         case NS_ERROR:
07143           BADBRANCHCONT;
07144           break;
07145 
07146         default:
07147           llgenindentmsg
07148             (message ("<error case> Storage %q becomes %s",
07149                       sRef_unparse (s), 
07150                       nstate_unparse (s->nullstate)),
07151              sRef_getNullInfoLoc (s));
07152           
07153           break;
07154         }
07155     }
07156 }
07157 
07158 void
07159 sRef_showAliasInfo (sRef s)
07160 {
07161   if (sRef_hasAliasInfoLoc (s))
07162     {
07163       if (sRef_isFresh (s))
07164         {
07165           llgenindentmsg 
07166             (message ("Fresh storage %qallocated", sRef_unparseOpt (s)),
07167              sRef_getAliasInfoLoc (s));
07168         }
07169       else 
07170         {
07171           if (!sRef_isRefCounted (s))
07172             {
07173               llgenindentmsg 
07174                 (message ("Storage %qbecomes %s", 
07175                           sRef_unparseOpt (s),
07176                           alkind_unparse (sRef_getAliasKind (s))),
07177                  sRef_getAliasInfoLoc (s));
07178             }
07179         }
07180     }
07181 }
07182 
07183 void
07184 sRef_mergeNullState (sRef s, nstate n)
07185 {
07186   if (sRef_isValid (s))
07187     {
07188       nstate old;
07189       
07190       old = s->nullstate;
07191       
07192       if (n != old && n != NS_UNKNOWN)
07193         {
07194                   
07195           s->nullstate = n;
07196           s->nullinfo = alinfo_updateLoc (s->nullinfo, g_currentloc);
07197         }
07198     }
07199   else
07200     {
07201       llbuglit ("sRef_mergeNullState: invalid");
07202     }
07203 }
07204 
07205 bool
07206 sRef_possiblyNull (sRef s)
07207 {
07208   if (sRef_isValid (s))
07209     {
07210       if (s->nullstate == NS_ABSNULL)
07211         {
07212           ctype rct = ctype_realType (s->type);
07213 
07214           if (ctype_isAbstract (rct))
07215             {
07216               return FALSE;
07217             }
07218           else
07219             {
07220               if (ctype_isUser (rct))
07221                 {
07222                   uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
07223                   
07224                   return (nstate_possiblyNull
07225                           (sRef_getNullState (uentry_getSref (ue))));
07226                 }
07227               else
07228                 {
07229                   return FALSE;
07230                 }
07231             }
07232         }
07233       else
07234         {
07235           return nstate_possiblyNull (s->nullstate);
07236         }
07237     }
07238 
07239   return FALSE;
07240 }
07241 
07242 cstring
07243 sRef_getScopeName (sRef s)
07244 {
07245   sRef base = sRef_getRootBase (s);
07246 
07247   if (sRef_isRealGlobal (base))
07248     {
07249       return (cstring_makeLiteralTemp ("Global"));
07250     }
07251   else if (sRef_isFileStatic (base))
07252     {
07253       return (cstring_makeLiteralTemp ("Static"));
07254     }
07255   else
07256     {
07257       return (cstring_makeLiteralTemp ("Local"));
07258     }
07259 }
07260 
07261 cstring
07262 sRef_unparseScope (sRef s)
07263 {
07264   sRef base = sRef_getRootBase (s);
07265 
07266   if (sRef_isRealGlobal (base))
07267     {
07268       return (cstring_makeLiteralTemp ("global"));
07269     }
07270   else if (sRef_isFileStatic (base))
07271     {
07272       return (cstring_makeLiteralTemp ("file static"));
07273     }
07274   else
07275     {
07276       BADEXIT;
07277     }
07278 }
07279 
07280 int
07281 sRef_getScope (sRef s)
07282 {
07283   llassert (sRef_isValid (s));
07284 
07285   if (sRef_isCvar (s))
07286     {
07287       return s->info->cvar->lexlevel;
07288     }
07289   else if (sRef_isParam (s))
07290     {
07291       return paramsScope;
07292     }
07293   else
07294     {
07295       return fileScope;
07296     }
07297 }
07298 
07299 bool
07300 sRef_isDead (sRef s)
07301 {
07302   return (sRef_isValid (s) && (s)->defstate == SS_DEAD);
07303 }
07304 
07305 bool
07306 sRef_isDeadStorage (sRef s)
07307 {
07308   if (sRef_isValid (s))
07309     {
07310       if (s->defstate == SS_DEAD
07311           || s->defstate == SS_UNUSEABLE
07312           || s->defstate == SS_UNDEFINED
07313           || s->defstate == SS_UNKNOWN)
07314         {
07315           return TRUE;
07316         }
07317       else 
07318         {
07319           return (sRef_isDefinitelyNull (s));
07320         }
07321     }
07322   else
07323     {
07324       return FALSE;
07325     }
07326 }
07327 
07328 bool
07329 sRef_isPossiblyDead (sRef s)
07330 {
07331   return (sRef_isValid (s) && s->defstate == SS_HOFFA);
07332 }
07333 
07334 bool sRef_isStateLive (sRef s)
07335 {
07336   if (sRef_isValid (s))
07337     {
07338       sstate ds = s->defstate;
07339 
07340       return (!(ds == SS_UNDEFINED 
07341                 || ds == SS_DEAD
07342                 || ds == SS_UNUSEABLE
07343                 || ds == SS_HOFFA));
07344     }
07345   else
07346     {
07347       return FALSE;
07348     }
07349 }
07350 
07351 
07352 bool sRef_isStateUndefined (sRef s)
07353 {
07354   return ((sRef_isValid(s)) && ((s)->defstate == SS_UNDEFINED));
07355 }
07356 
07357 bool sRef_isJustAllocated (sRef s)
07358 {
07359   if (sRef_isAllocated (s))
07360     {
07361       sRefSet_allElements (s->deriv, el)
07362         {
07363           if (!(sRef_isStateUndefined (el) || sRef_isUnuseable (el)))
07364             {
07365               return FALSE;
07366             }
07367         } end_sRefSet_allElements ;
07368 
07369       return TRUE;
07370     }
07371 
07372   return FALSE;
07373 }
07374 
07375 static bool
07376 sRef_isAllocatedStorage (sRef s)
07377 {
07378   if (sRef_isValid (s) && ynm_toBoolStrict (sRef_isReadable (s)))
07379     {
07380       return (ctype_isVisiblySharable (sRef_getType (s)));
07381     }
07382   else
07383     {
07384       return FALSE;
07385     }
07386 }
07387 
07388 bool
07389 sRef_isUnuseable (sRef s)
07390 {
07391   return ((sRef_isValid(s)) && ((s)->defstate == SS_UNUSEABLE));
07392 }
07393 
07394 bool
07395 sRef_perhapsNull (sRef s)
07396 {
07397   if (sRef_isValid (s))
07398     {
07399       if (s->nullstate == NS_ABSNULL)
07400         {
07401           ctype rct = ctype_realType (s->type);
07402 
07403           if (ctype_isAbstract (rct))
07404             {
07405               return FALSE;
07406             }
07407           else
07408             {
07409               if (ctype_isUser (rct))
07410                 {
07411                   uentry ue = usymtab_getTypeEntry (ctype_typeId (rct));
07412 
07413                   return (nstate_perhapsNull 
07414                           (sRef_getNullState (uentry_getSref (ue))));
07415                 }
07416               else
07417                 {
07418                   return FALSE;
07419                 }
07420             }
07421         }
07422       else
07423         {
07424           return nstate_perhapsNull (s->nullstate);
07425         }
07426     }
07427 
07428   return FALSE;
07429 }
07430 
07431 /*
07432 ** definitelyNull --- called when TRUE is good
07433 */
07434 
07435 bool 
07436 sRef_definitelyNull (sRef s)
07437 {
07438   return (sRef_isValid (s)
07439           && (s->nullstate == NS_DEFNULL || s->nullstate == NS_CONSTNULL));
07440 }
07441 
07442 /*
07443 ** based on sRef_similar
07444 */
07445 
07446 void
07447 sRef_setDerivNullState (sRef set, sRef guide, nstate ns)
07448 {
07449   if (sRef_isValid (set))
07450     {
07451       sRef deriv = sRef_getDeriv (set, guide);
07452       
07453       if (sRef_isValid (deriv))
07454         {
07455           deriv->nullstate = ns;
07456         }
07457     }
07458 }
07459 
07460 static /*@exposed@*/ sRef
07461 sRef_getDeriv (/*@returned@*/ /*@notnull@*/ sRef set, sRef guide)
07462 {
07463   llassert (sRef_isValid (set));
07464   llassert (sRef_isValid (guide));
07465 
07466   switch (guide->kind)
07467     {
07468     case SK_CVAR:
07469       llassert (set->kind == SK_CVAR);
07470       
07471       return set;
07472 
07473     case SK_PARAM:
07474       llassert (set->kind == guide->kind);
07475       llassert (set->info->paramno == guide->info->paramno);
07476 
07477       return set;
07478 
07479     case SK_ARRAYFETCH:
07480 
07481       if (set->kind == SK_ARRAYFETCH
07482           && (sRef_similar (set->info->arrayfetch->arr,
07483                             guide->info->arrayfetch->arr)))
07484         {
07485           return set;
07486         }
07487       else
07488         {
07489           return (sRef_makeAnyArrayFetch 
07490                   (sRef_getDeriv (set, guide->info->arrayfetch->arr)));
07491         }
07492 
07493     case SK_PTR:
07494       
07495       if (set->kind == SK_PTR && sRef_similar (set->info->ref, guide->info->ref))
07496         {
07497           return set;
07498         }
07499       else
07500         {
07501           return (sRef_makePointer (sRef_getDeriv (set, guide->info->ref)));
07502         }
07503       
07504     case SK_FIELD:
07505       
07506       if ((set->kind == SK_FIELD &&
07507            (sRef_similar (set->info->field->rec, guide->info->field->rec) &&
07508             cstring_equal (set->info->field->field, guide->info->field->field))))
07509         {
07510           return set;
07511         }
07512       else
07513         {
07514           return (sRef_makeField (sRef_getDeriv (set, guide->info->field->rec),
07515                                   guide->info->field->field));
07516         }
07517     case SK_ADR:
07518       
07519       if ((set->kind == SK_ADR) && sRef_similar (set->info->ref, guide->info->ref))
07520         {
07521           return set;
07522         }
07523       else
07524         {
07525           return (sRef_makeAddress (sRef_getDeriv (set, guide->info->ref)));
07526         }
07527 
07528     case SK_CONJ:
07529       
07530             return sRef_undefined;
07531 
07532     case SK_RESULT:
07533     case SK_SPECIAL:
07534     case SK_UNCONSTRAINED:
07535     case SK_TYPE:
07536     case SK_CONST:
07537     case SK_NEW:
07538     case SK_UNKNOWN:
07539     case SK_OBJECT:
07540     case SK_DERIVED:
07541     case SK_EXTERNAL:
07542       return sRef_undefined;
07543     }
07544 
07545   BADEXIT;
07546 }
07547       
07548 /*
07549 ** sRef_aliasCheckPred
07550 **
07551 ** A confusing but spiffy function:
07552 **
07553 **    Calls predf (s, e, text, <alias>) on s and all of s's aliases
07554 **    (unless checkAliases (s) is FALSE).
07555 **
07556 **    For alias calls, calls as
07557 **          predf (alias, e, text, s)
07558 */
07559 
07560 void
07561 sRef_aliasCheckPred (bool (predf) (sRef, exprNode, sRef, exprNode),
07562                      /*@null@*/ bool (checkAliases) (sRef),
07563                      sRef s, exprNode e, exprNode err)
07564 {
07565   bool error = (*predf)(s, e, sRef_undefined, err);
07566   
07567   
07568   if (checkAliases != NULL && !(checkAliases (s)))
07569     {
07570       /* don't check aliases */
07571     }
07572   else
07573     {
07574       sRefSet aliases = usymtab_allAliases (s);
07575 
07576       
07577       sRefSet_realElements (aliases, current)
07578         {
07579           if (sRef_isValid (current))
07580             {
07581               if (!sRef_similar (current, s)
07582                   || (error && sRef_sameName (current, s)))
07583                 {
07584                   (void) (*predf)(current, e, s, err);
07585                 }
07586               }
07587         } end_sRefSet_realElements;
07588 
07589       sRefSet_free (aliases);
07590     }
07591 }
07592 
07593 /*
07594 ** return TRUE iff predf (s) is true for s or any alias of s
07595 */
07596 
07597 bool
07598 sRef_aliasCheckSimplePred (sRefTest predf, sRef s)
07599 {
07600     
07601   if ((*predf)(s))
07602     {
07603       return TRUE;
07604     }
07605   else
07606     {
07607       sRefSet aliases;
07608 
07609       aliases = usymtab_allAliases (s);
07610       
07611       sRefSet_realElements (aliases, current)
07612         {
07613           if (sRef_isValid (current))
07614             {
07615               sRef cref = sRef_updateSref (current);
07616               
07617               /* Whoa! a very kludgey way to make sure the right sref is used
07618               ** where there is a conditional symbol table.  I am beginning
07619               ** to think that having a conditional symbol table wasn't such
07620               ** a great idea.  ;(
07621               */
07622               
07623                       
07624               if ((*predf)(cref))
07625                 {
07626                   sRefSet_free (aliases);
07627                   return TRUE;
07628                 }
07629             }
07630         } end_sRefSet_realElements;
07631 
07632       sRefSet_free (aliases);
07633     }
07634   return FALSE;
07635 }
07636 
07637 bool
07638 sRef_aliasCompleteSimplePred (bool (predf) (sRef), sRef s)
07639 {
07640   sRefSet aliases;
07641   bool result = FALSE;
07642   
07643   
07644   aliases = usymtab_allAliases (s);
07645   
07646   if ((*predf)(s)) result = TRUE;
07647 
07648   
07649   sRefSet_realElements (aliases, current)
07650     {
07651       if (sRef_isValid (current))
07652         {
07653                   current = sRef_updateSref (current);
07654                   if ((*predf)(current)) result = TRUE;
07655         }
07656     } end_sRefSet_realElements;
07657   
07658   sRefSet_free (aliases);
07659   return result;
07660 }
07661 
07662 static void
07663 sRef_aliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
07664 {
07665   sRefSet aliases;
07666   
07667   aliases = usymtab_allAliases (s);
07668 
07669   (*predf)(s, loc);
07670 
07671   sRefSet_realElements (aliases, current)
07672     {
07673       if (sRef_isValid (current))
07674         {
07675           current = sRef_updateSref (current);
07676                   ((*predf)(current, loc));
07677         }
07678     } end_sRefSet_realElements;
07679 
07680   sRefSet_free (aliases);
07681 }
07682 
07683 static void
07684 sRef_aliasSetCompleteParam (void (predf) (sRef, alkind, fileloc), sRef s, 
07685                             alkind kind, fileloc loc)
07686 {
07687   sRefSet aliases;
07688 
07689   
07690   if (sRef_isDeep (s))
07691     {
07692       aliases = usymtab_allAliases (s);
07693     }
07694   else
07695     {
07696       aliases = usymtab_aliasedBy (s);
07697     }
07698 
07699   (*predf)(s, kind, loc);
07700 
07701   sRefSet_realElements (aliases, current)
07702     {
07703       if (sRef_isValid (current))
07704         {
07705           current = sRef_updateSref (current);
07706                   ((*predf)(current, kind, loc));
07707         }
07708     } end_sRefSet_realElements;
07709 
07710   sRefSet_free (aliases);
07711 }
07712 
07713 static void
07714 sRef_innerAliasSetComplete (void (predf) (sRef, fileloc), sRef s, fileloc loc)
07715 {
07716   sRef inner;
07717   sRefSet aliases;
07718   ctype ct;
07719 
07720   if (!sRef_isValid (s)) return;
07721 
07722   
07723   /*
07724   ** Type equivalence checking is necessary --- there might be casting.
07725   */
07726 
07727   (*predf)(s, loc);
07728 
07729   switch (s->kind)
07730     {
07731     case SK_UNCONSTRAINED:
07732     case SK_CVAR:
07733     case SK_PARAM:
07734       break;
07735     case SK_PTR:
07736       inner = s->info->ref;
07737       aliases = usymtab_allAliases (inner);
07738       ct = sRef_getType (inner);
07739 
07740       
07741       sRefSet_realElements (aliases, current)
07742         {
07743           if (sRef_isValid (current))
07744             {
07745               current = sRef_updateSref (current);
07746               
07747               if (ctype_equal (ct, sRef_getType (current)))
07748                 {
07749                   sRef ptr = sRef_makePointer (current);
07750                   
07751                   ((*predf)(ptr, loc));
07752                 }
07753             }
07754         } end_sRefSet_realElements;
07755 
07756       sRefSet_free (aliases);
07757       break;
07758     case SK_ARRAYFETCH:
07759       inner = s->info->arrayfetch->arr;
07760       aliases = usymtab_allAliases (inner);
07761       ct = sRef_getType (inner);
07762 
07763       sRefSet_realElements (aliases, current)
07764         {
07765           if (sRef_isValid (current))
07766             {
07767               current = sRef_updateSref (current);
07768               
07769               if (ctype_equal (ct, sRef_getType (current)))
07770                 {
07771                                   
07772                   if (s->info->arrayfetch->indknown)
07773                     {
07774                       sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
07775                       
07776                       ((*predf)(af, loc));
07777                     }
07778                   else
07779                     {
07780                       sRef af = sRef_makeArrayFetch (current);
07781                       
07782                       ((*predf)(af, loc));
07783                     }
07784                 }
07785             }
07786         } end_sRefSet_realElements;
07787 
07788       sRefSet_free (aliases);
07789       break;
07790     case SK_FIELD:
07791       inner = s->info->field->rec;
07792       aliases = usymtab_allAliases (inner);
07793       ct = sRef_getType (inner);
07794 
07795       
07796       sRefSet_realElements (aliases, current)
07797         {
07798           if (sRef_isValid (current))
07799             {
07800               current = sRef_updateSref (current);
07801               
07802               if (ctype_equal (ct, sRef_getType (current)))
07803                 {
07804                   sRef f = sRef_makeField (current, s->info->field->field);
07805                   
07806                   ((*predf)(f, loc));
07807                 }
07808             }
07809         } end_sRefSet_realElements;
07810       
07811       sRefSet_free (aliases);
07812       break;
07813     case SK_CONJ:
07814       sRef_innerAliasSetComplete (predf, s->info->conj->a, loc);
07815       sRef_innerAliasSetComplete (predf, s->info->conj->b, loc);
07816       break;
07817     case SK_SPECIAL:
07818     case SK_ADR:
07819     case SK_TYPE:
07820     case SK_CONST:
07821     case SK_NEW:
07822     case SK_UNKNOWN:
07823     case SK_OBJECT:
07824     case SK_DERIVED:
07825     case SK_EXTERNAL:
07826     case SK_RESULT:
07827       break;
07828     }
07829 }
07830 
07831 static void
07832 sRef_innerAliasSetCompleteParam (void (predf) (sRef, sRef), sRef s, sRef t)
07833 {
07834   sRef inner;
07835   sRefSet aliases;
07836   ctype ct;
07837 
07838   if (!sRef_isValid (s)) return;
07839 
07840   
07841   /*
07842   ** Type equivalence checking is necessary --- there might be casting.
07843   */
07844 
07845   (*predf)(s, t);
07846 
07847   switch (s->kind)
07848     {
07849     case SK_UNCONSTRAINED:
07850     case SK_CVAR:
07851     case SK_PARAM:
07852       break;
07853     case SK_PTR:
07854       inner = s->info->ref;
07855       aliases = usymtab_allAliases (inner);
07856       ct = sRef_getType (inner);
07857       
07858       
07859       sRefSet_realElements (aliases, current)
07860         {
07861           if (sRef_isValid (current))
07862             {
07863               current = sRef_updateSref (current);
07864               
07865               if (ctype_equal (ct, sRef_getType (current)))
07866                 {
07867                   sRef ptr = sRef_makePointer (current);
07868                   
07869                   ((*predf)(ptr, t));
07870                 }
07871             }
07872         } end_sRefSet_realElements;
07873 
07874       sRefSet_free (aliases);
07875       break;
07876     case SK_ARRAYFETCH:
07877       inner = s->info->arrayfetch->arr;
07878       aliases = usymtab_allAliases (inner);
07879       ct = sRef_getType (inner);
07880 
07881       sRefSet_realElements (aliases, current)
07882         {
07883           if (sRef_isValid (current))
07884             {
07885               current = sRef_updateSref (current);
07886               
07887               if (ctype_equal (ct, sRef_getType (current)))
07888                 {
07889                                   
07890                   if (s->info->arrayfetch->indknown)
07891                     {
07892                       sRef af = sRef_makeArrayFetchKnown (current, s->info->arrayfetch->ind);
07893                       
07894                       ((*predf)(af, t));
07895                     }
07896                   else
07897                     {
07898                       sRef af = sRef_makeArrayFetch (current);
07899                       
07900                       ((*predf)(af, t));
07901                     }
07902                 }
07903             }
07904         } end_sRefSet_realElements;
07905 
07906       sRefSet_free (aliases);
07907       break;
07908     case SK_FIELD:
07909       inner = s->info->field->rec;
07910       aliases = usymtab_allAliases (inner);
07911       ct = sRef_getType (inner);
07912 
07913       
07914       sRefSet_realElements (aliases, current)
07915         {
07916           if (sRef_isValid (current))
07917             {
07918               current = sRef_updateSref (current);
07919               
07920               if (ctype_equal (ct, sRef_getType (current)))
07921                 {
07922                   sRef f = sRef_makeField (current, s->info->field->field);
07923                   
07924                   ((*predf)(f, t));
07925                 }
07926             }
07927         } end_sRefSet_realElements;
07928       
07929       sRefSet_free (aliases);
07930       break;
07931     case SK_CONJ:
07932       sRef_innerAliasSetCompleteParam (predf, s->info->conj->a, t);
07933       sRef_innerAliasSetCompleteParam (predf, s->info->conj->b, t);
07934       break;
07935     case SK_SPECIAL:
07936     case SK_ADR:
07937     case SK_TYPE:
07938     case SK_CONST:
07939     case SK_NEW:
07940     case SK_UNKNOWN:
07941     case SK_OBJECT:
07942     case SK_DERIVED:
07943     case SK_EXTERNAL:
07944     case SK_RESULT:
07945       break;
07946     }
07947 }
07948 
07949 static void sRef_combineExKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
07950 {
07951   exkind a1 = sRef_getExKind (res);
07952   exkind a2 = sRef_getExKind (other);
07953 
07954   if (a1 == a2 || a2 == XO_UNKNOWN) 
07955     {
07956       ;
07957     }
07958   else if (a1 == XO_UNKNOWN) 
07959     { 
07960       res->expinfo = alinfo_update (res->expinfo, other->expinfo);
07961       res->expkind = a2;
07962     }
07963   else
07964     {
07965       res->expkind = XO_OBSERVER;
07966     }
07967 }
07968 
07969 /*
07970 ** Currently, this is a very ad hoc implementation, with lots of fixes to
07971 ** make real code work okay.  I need to come up with some more general
07972 ** rules or principles here.
07973 */
07974 
07975 static void 
07976   sRef_combineAliasKindsError (/*@notnull@*/ sRef res, 
07977                                /*@notnull@*/ sRef other, 
07978                                clause cl, fileloc loc)
07979 {
07980   bool hasError = FALSE;
07981   alkind ares = sRef_getAliasKind (res);
07982   alkind aother = sRef_getAliasKind (other);
07983 
07984   if (alkind_isDependent (ares))
07985     {
07986       if (aother == AK_KEPT)
07987         {
07988           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
07989           res->aliaskind = AK_KEPT;      
07990         }
07991       else 
07992         {
07993           if (aother == AK_LOCAL || aother == AK_STATIC 
07994               || alkind_isTemp (aother))
07995             {
07996               res->aliaskind = AK_DEPENDENT;
07997             }
07998         }
07999     }
08000   else if (alkind_isDependent (aother))
08001     {
08002       if (ares == AK_KEPT)
08003         {
08004           res->aliaskind = AK_KEPT;      
08005         }
08006       else 
08007         {
08008           if (ares == AK_LOCAL || ares == AK_STATIC || alkind_isTemp (ares))
08009             {
08010               res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
08011               res->aliaskind = AK_DEPENDENT;
08012             }
08013         }
08014     }
08015   else if ((ares == AK_LOCAL || ares == AK_UNIQUE
08016             || ares == AK_STATIC || alkind_isTemp (ares))
08017            && sRef_isFresh (other))
08018     {
08019       /*
08020       ** cases like: if (s == NULL) s = malloc...;
08021       **    don't generate errors
08022       */
08023       
08024       if (usymtab_isAltProbablyDeepNull (res))
08025         {
08026           res->aliaskind = ares;
08027         }
08028       else
08029         {
08030           hasError = TRUE; 
08031         }
08032     }
08033   else if ((aother == AK_LOCAL || aother == AK_UNIQUE
08034             || aother == AK_STATIC || alkind_isTemp (aother))
08035            && sRef_isFresh (res))
08036     {
08037       /*
08038       ** cases like: if (s == NULL) s = malloc...;
08039       **    don't generate errors
08040       */
08041       
08042       if (usymtab_isProbableDeepNull (other))
08043         {
08044           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
08045           res->aliaskind = aother;
08046         }
08047       else
08048         {
08049           hasError = TRUE;
08050         }
08051     }
08052   else if (ares == AK_NEWREF && aother == AK_REFCOUNTED 
08053            && sRef_isConst (other))
08054     {
08055       res->aliaskind = AK_NEWREF;
08056     }
08057   else if (aother == AK_NEWREF && ares == AK_REFCOUNTED
08058            && sRef_isConst (res))
08059     {
08060       res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
08061       res->aliaskind = AK_NEWREF;
08062     }
08063   else if (sRef_isLocalVar (res)
08064            && ((ares == AK_KEPT && aother == AK_LOCAL)
08065                || (aother == AK_KEPT && ares == AK_LOCAL)))
08066     {
08067       res->aliaskind = AK_KEPT;
08068     }
08069   else
08070     {
08071       hasError = TRUE;
08072     }
08073 
08074   if (hasError)
08075     {
08076       if (sRef_isThroughArrayFetch (res))
08077         {
08078           if (optgenerror2 
08079               (FLG_BRANCHSTATE, FLG_STRICTBRANCHSTATE,
08080                message
08081                ("Clauses exit with %q possibly referencing %s storage %s, "
08082                 "%s storage %s", 
08083                 sRef_unparse (res),
08084                 alkind_unparse (aother),
08085                 clause_nameTaken (cl),
08086                 alkind_unparse (ares),
08087                 clause_nameAlternate (cl)),
08088                loc))
08089             {
08090               sRef_showAliasInfo (res);
08091               sRef_showAliasInfo (other);
08092               res->aliaskind = AK_ERROR;
08093             }
08094           else
08095             {
08096               if (ares == AK_KEPT || aother == AK_KEPT)
08097                 {
08098                   sRef_maybeKill (res, loc);
08099                                 }
08100             }
08101         }
08102       else 
08103         {
08104           if (optgenerror 
08105               (FLG_BRANCHSTATE,
08106                message ("Clauses exit with %q referencing %s storage %s, "
08107                         "%s storage %s", 
08108                         sRef_unparse (res),
08109                         alkind_unparse (aother),
08110                         clause_nameTaken (cl),
08111                         alkind_unparse (ares),
08112                         clause_nameAlternate (cl)),
08113                loc))
08114             {
08115               sRef_showAliasInfo (res);
08116               sRef_showAliasInfo (other);
08117               
08118               res->aliaskind = AK_ERROR;
08119             }
08120         }
08121       
08122       res->aliaskind = (sRef_isLocalVar (res) ? AK_LOCAL : AK_UNKNOWN);
08123     }
08124 }
08125 
08126 static void 
08127   sRef_combineAliasKinds (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other, 
08128                           clause cl, fileloc loc)
08129 {
08130   alkind ares = sRef_getAliasKind (res);
08131   alkind aother = sRef_getAliasKind (other);
08132 
08133   if (alkind_equal (ares, aother)
08134       || aother == AK_UNKNOWN
08135       || aother == AK_ERROR)
08136     {
08137       ; /* keep current state */
08138     }
08139   else if (sRef_isDead (res) || sRef_isDead (other))
08140     {
08141       /* dead error reported (or storage is dead) */
08142       res ->aliaskind = AK_ERROR; 
08143     }
08144   else if (ares == AK_UNKNOWN || ares == AK_ERROR
08145            || sRef_isStateUndefined (res))
08146     { 
08147       res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
08148       res->aliaskind = aother;  
08149     }
08150   else if (sRef_isStateUndefined (other))
08151     {
08152       ;
08153     }
08154   else if (((ares == AK_UNIQUE || alkind_isTemp (ares))
08155             && aother == AK_LOCAL) 
08156            || ((aother == AK_UNIQUE || alkind_isTemp (aother))
08157                && ares == AK_LOCAL))
08158     {
08159       if (ares != AK_LOCAL)
08160         {
08161           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
08162         }
08163 
08164       res->aliaskind = AK_LOCAL;
08165     }
08166   else if ((ares == AK_OWNED && aother == AK_FRESH) 
08167            || (aother == AK_OWNED && ares == AK_FRESH))
08168     {
08169       if (ares != AK_FRESH)
08170         {
08171           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
08172         }
08173       
08174       res->aliaskind = AK_FRESH;
08175     }
08176   else if ((ares == AK_KEEP && aother == AK_FRESH) ||
08177            (aother == AK_KEEP && ares == AK_FRESH))
08178     {
08179       if (ares != AK_KEEP)
08180         {
08181           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
08182         }
08183       
08184       res->aliaskind = AK_KEEP;
08185     }
08186   else if ((ares == AK_LOCAL && aother == AK_STACK) ||
08187            (aother == AK_LOCAL && ares == AK_STACK))
08188     {
08189       if (ares != AK_STACK)
08190         {
08191           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
08192         }
08193 
08194       res->aliaskind = AK_STACK;
08195     }
08196   else if ((ares == AK_LOCAL
08197             && (aother == AK_OWNED && sRef_isLocalVar (other)))
08198            || (aother == AK_LOCAL 
08199                && (ares == AK_OWNED && sRef_isLocalVar (res))))
08200     {
08201       if (ares != AK_LOCAL)
08202         {
08203           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
08204         }
08205 
08206       res->aliaskind = AK_LOCAL;
08207     }
08208   else if ((ares == AK_FRESH && alkind_isOnly (aother))
08209            || (aother == AK_FRESH && alkind_isOnly (ares)))
08210     {
08211       res->aliaskind = AK_FRESH;
08212     }
08213   else if ((aother == AK_FRESH && sRef_definitelyNull (res))
08214            || (ares == AK_FRESH && sRef_definitelyNull (other)))
08215     {
08216       if (ares != AK_FRESH)
08217         {
08218           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
08219           res->aliaskind = AK_FRESH;
08220         }
08221     }
08222   else if ((sRef_isFresh (res) && sRef_isConst (other))
08223            || (sRef_isFresh (other) && sRef_isConst (res)))
08224     {
08225       /*
08226       ** for NULL constantants
08227       ** this is bogus!
08228       */
08229 
08230       if (!sRef_isFresh (res))
08231         {
08232           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
08233         }
08234 
08235       res->aliaskind = AK_FRESH;
08236     }
08237   else if ((alkind_isStatic (aother) && sRef_isConst (res))
08238            || (alkind_isStatic (ares) && sRef_isConst (other)))
08239     {
08240       if (!alkind_isStatic (ares))
08241         {
08242           res->aliasinfo = alinfo_update (res->aliasinfo, other->aliasinfo);
08243           res->aliaskind = AK_STATIC;
08244         }
08245     }
08246   else
08247     {
08248       sRef_combineAliasKindsError (res, other, cl, loc);
08249     }
08250 }
08251 
08252 static void sRef_combineDefState (/*@notnull@*/ sRef res, 
08253                                   /*@notnull@*/ sRef other)
08254 {
08255   sstate s1 = res->defstate;
08256   sstate s2 = other->defstate;
08257   bool flip = FALSE;
08258 
08259   if (s1 == s2 || s2 == SS_UNKNOWN)
08260     {
08261       ;
08262     }
08263   else if (s1 == SS_UNKNOWN)
08264     {
08265       flip = TRUE;
08266     }
08267   else
08268     {
08269       switch (s1)
08270         {
08271         case SS_FIXED:   
08272           if (s2 == SS_DEFINED) 
08273             {
08274               break;
08275             }
08276           else
08277             {
08278               llcontbuglit ("ssfixed: not implemented");
08279               flip = TRUE;
08280             }
08281           break;
08282         case SS_DEFINED: 
08283           flip = TRUE;
08284           break;
08285         case SS_PDEFINED:
08286         case SS_ALLOCATED: 
08287           flip = (s2 != SS_DEFINED);
08288           break;
08289         case SS_HOFFA:
08290         case SS_RELDEF:
08291         case SS_UNUSEABLE: 
08292         case SS_UNDEFINED: 
08293         case SS_PARTIAL:
08294         case SS_UNDEFGLOB:
08295         case SS_KILLED:
08296         case SS_DEAD:      
08297         case SS_SPECIAL: 
08298           break;
08299         BADDEFAULT;
08300         }
08301     }
08302 
08303   if (flip)
08304     {
08305       res->definfo = alinfo_update (res->definfo, other->definfo);
08306       res->defstate = s2;
08307     }
08308 }
08309 
08310 extern /*@notnull@*/ sRef sRef_getConjA (sRef s)
08311 {
08312   sRef ret;
08313   llassert (sRef_isConj (s));
08314 
08315   ret = s->info->conj->a;
08316   llassert (ret != NULL);
08317   return ret;
08318 }
08319 
08320 extern /*@notnull@*/ sRef sRef_getConjB (sRef s)
08321 {
08322   sRef ret;
08323   llassert (sRef_isConj (s));
08324 
08325   ret = s->info->conj->b;
08326   llassert (ret != NULL);
08327   return ret;
08328 }
08329   
08330 extern /*@exposed@*/ sRef sRef_makeArrow (sRef s, /*@dependent@*/ cstring f)
08331 {
08332   sRef p;
08333   sRef ret;
08334 
08335     p = sRef_makePointer (s);
08336   ret = sRef_makeField (p, f);
08337     return ret;
08338 }
08339 
08340 extern /*@exposed@*/ sRef sRef_buildArrow (sRef s, cstring f)
08341 {
08342   sRef p;
08343   sRef ret;
08344 
08345   p = sRef_buildPointer (s);
08346   ret = sRef_buildField (p, f);
08347   
08348   return ret;
08349 }
08350 
08351 static /*@null@*/ sinfo sinfo_copy (/*@notnull@*/ sRef s)
08352 {
08353   sinfo ret;
08354 
08355   switch (s->kind)
08356     {
08357     case SK_CVAR:
08358       ret = (sinfo) dmalloc (sizeof (*ret));
08359       ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
08360       ret->cvar->lexlevel = s->info->cvar->lexlevel; 
08361       ret->cvar->index = s->info->cvar->index; 
08362       break;
08363 
08364     case SK_PARAM:
08365       ret = (sinfo) dmalloc (sizeof (*ret));
08366       ret->paramno = s->info->paramno; 
08367       break;
08368 
08369     case SK_ARRAYFETCH:
08370       ret = (sinfo) dmalloc (sizeof (*ret));
08371       ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
08372       ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
08373       ret->arrayfetch->ind = s->info->arrayfetch->ind;
08374       ret->arrayfetch->arr = s->info->arrayfetch->arr;
08375       break;
08376 
08377     case SK_FIELD:
08378       ret = (sinfo) dmalloc (sizeof (*ret));
08379       ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
08380       ret->field->rec = s->info->field->rec;
08381       ret->field->field = s->info->field->field; 
08382       break;
08383 
08384     case SK_OBJECT:
08385       ret = (sinfo) dmalloc (sizeof (*ret));
08386       ret->object = s->info->object;
08387       break;
08388 
08389     case SK_PTR:
08390     case SK_ADR:
08391     case SK_DERIVED:
08392     case SK_EXTERNAL:
08393       ret = (sinfo) dmalloc (sizeof (*ret));
08394       ret->ref = s->info->ref;   
08395       break;
08396 
08397     case SK_CONJ:
08398       ret = (sinfo) dmalloc (sizeof (*ret));
08399       ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
08400       ret->conj->a = s->info->conj->a;
08401       ret->conj->b = s->info->conj->b;
08402       break;
08403     case SK_SPECIAL:
08404       ret = (sinfo) dmalloc (sizeof (*ret));
08405       ret->spec = s->info->spec;
08406       break;
08407     case SK_UNCONSTRAINED:
08408     case SK_NEW:
08409       ret = (sinfo) dmalloc (sizeof (*ret));
08410       ret->fname = s->info->fname;
08411       break;
08412     case SK_RESULT:
08413     case SK_CONST:
08414     case SK_TYPE:
08415     case SK_UNKNOWN:
08416       llassertprint (s->info == NULL, ("s = %s", sRef_unparse (s)));
08417       ret = NULL;
08418       break;
08419     }
08420 
08421   return ret;
08422 }
08423 
08424 static /*@null@*/ sinfo sinfo_fullCopy (/*@notnull@*/ sRef s)
08425 {
08426   sinfo ret;
08427 
08428   /*
08429   ** Since its a full copy, only storage is assigned
08430   ** to dependent fields.
08431   */
08432   /*@-onlytrans@*/
08433 
08434   switch (s->kind)
08435     {
08436     case SK_CVAR:
08437       ret = (sinfo) dmalloc (sizeof (*ret));
08438       ret->cvar = (cref) dmalloc (sizeof (*ret->cvar));
08439       ret->cvar->lexlevel = s->info->cvar->lexlevel; 
08440       ret->cvar->index = s->info->cvar->index; 
08441       break;
08442 
08443     case SK_PARAM:
08444       ret = (sinfo) dmalloc (sizeof (*ret));
08445       ret->paramno = s->info->paramno; 
08446       break;
08447 
08448     case SK_ARRAYFETCH:
08449       ret = (sinfo) dmalloc (sizeof (*ret));
08450       ret->arrayfetch = (ainfo) dmalloc (sizeof (*ret->arrayfetch));
08451       ret->arrayfetch->indknown = s->info->arrayfetch->indknown;
08452       ret->arrayfetch->ind = s->info->arrayfetch->ind;
08453       ret->arrayfetch->arr = sRef_saveCopy (s->info->arrayfetch->arr);
08454       break;
08455 
08456     case SK_FIELD:
08457       ret = (sinfo) dmalloc (sizeof (*ret));
08458       ret->field = (fldinfo) dmalloc (sizeof (*ret->field));
08459       ret->field->rec = sRef_saveCopy (s->info->field->rec);
08460       ret->field->field = s->info->field->field; 
08461       break;
08462 
08463     case SK_OBJECT:
08464       ret = (sinfo) dmalloc (sizeof (*ret));
08465       ret->object = s->info->object;
08466       break;
08467 
08468     case SK_PTR:
08469     case SK_ADR:
08470     case SK_DERIVED:
08471     case SK_EXTERNAL:
08472       ret = (sinfo) dmalloc (sizeof (*ret));
08473       ret->ref = sRef_saveCopy (s->info->ref);   
08474       break;
08475 
08476     case SK_CONJ:
08477       ret = (sinfo) dmalloc (sizeof (*ret));
08478       ret->conj = (cjinfo) dmalloc (sizeof (*ret->conj));
08479       ret->conj->a = sRef_saveCopy (s->info->conj->a);
08480       ret->conj->b = sRef_saveCopy (s->info->conj->b);
08481       break;
08482     case SK_SPECIAL:
08483       ret = (sinfo) dmalloc (sizeof (*ret));
08484       ret->spec = s->info->spec;
08485       break;
08486     case SK_NEW:
08487     case SK_UNCONSTRAINED:
08488       ret = (sinfo) dmalloc (sizeof (*ret));
08489       ret->fname = s->info->fname;
08490       break;
08491     case SK_CONST:
08492     case SK_TYPE:
08493     case SK_RESULT:
08494     case SK_UNKNOWN:
08495       llassert (s->info == NULL);
08496       ret = NULL;
08497       break;
08498     }
08499   /*@=onlytrans@*/ 
08500   return ret;
08501 }
08502 
08503 
08504 static void 
08505   sinfo_update (/*@notnull@*/ /*@exposed@*/ sRef res, 
08506                 /*@notnull@*/ /*@exposed@*/ sRef other)
08507 {
08508   llassert (res->kind == other->kind);
08509 
08510   switch (res->kind)
08511     {
08512     case SK_CVAR:
08513       res->info->cvar->lexlevel = other->info->cvar->lexlevel; 
08514       res->info->cvar->index = other->info->cvar->index; 
08515       break;
08516 
08517     case SK_PARAM:
08518       res->info->paramno = other->info->paramno; 
08519       break;
08520 
08521     case SK_ARRAYFETCH:
08522       res->info->arrayfetch->indknown = other->info->arrayfetch->indknown;
08523       res->info->arrayfetch->ind = other->info->arrayfetch->ind;
08524       res->info->arrayfetch->arr = other->info->arrayfetch->arr;
08525       break;
08526 
08527     case SK_FIELD:
08528       res->info->field->rec = other->info->field->rec;
08529       res->info->field->field = other->info->field->field; 
08530       break;
08531 
08532     case SK_OBJECT:
08533       res->info->object = other->info->object;
08534       break;
08535 
08536     case SK_PTR:
08537     case SK_ADR:
08538     case SK_DERIVED:
08539     case SK_EXTERNAL:
08540       res->info->ref = other->info->ref;         
08541       break;
08542 
08543     case SK_CONJ:
08544       res->info->conj->a = other->info->conj->a;
08545       res->info->conj->b = other->info->conj->b;
08546       break;
08547 
08548     case SK_SPECIAL:
08549       res->info->spec = other->info->spec;
08550       break;
08551 
08552     case SK_NEW:
08553     case SK_UNCONSTRAINED:
08554       res->info->fname = other->info->fname;
08555       break;
08556 
08557     case SK_CONST:
08558     case SK_TYPE:
08559     case SK_UNKNOWN:
08560     case SK_RESULT:
08561       llassert (res->info == NULL);
08562       break;
08563     }
08564 }
08565 
08566 static void sinfo_free (/*@special@*/ /*@temp@*/ /*@notnull@*/ sRef s)
08567    /*@uses s->kind, s->info@*/
08568    /*@releases s->info@*/ 
08569 {
08570   switch (s->kind)
08571     {
08572     case SK_CVAR:
08573       sfree (s->info->cvar);
08574       break;
08575 
08576     case SK_PARAM:
08577       break;
08578 
08579     case SK_ARRAYFETCH:
08580       sfree (s->info->arrayfetch);
08581       break;
08582 
08583     case SK_FIELD:
08584       sfree (s->info->field); 
08585       break;
08586 
08587     case SK_OBJECT:
08588       break;
08589 
08590     case SK_PTR:
08591     case SK_ADR:
08592     case SK_DERIVED:
08593     case SK_EXTERNAL:
08594       break;
08595 
08596     case SK_CONJ:
08597       sfree (s->info->conj);
08598       break;
08599 
08600     case SK_UNCONSTRAINED:
08601     case SK_SPECIAL:
08602     case SK_CONST:
08603     case SK_NEW:
08604     case SK_TYPE:
08605     case SK_UNKNOWN:
08606     case SK_RESULT:
08607       break;
08608     }
08609 
08610   sfree (s->info);
08611 }
08612 
08613 bool sRef_isNSLocalVar (sRef s)  
08614 {
08615   if (sRef_isLocalVar (s))
08616     {
08617       uentry ue = sRef_getUentry (s);
08618 
08619       return (!uentry_isStatic (ue));
08620     }
08621   else
08622     {
08623       return FALSE;
08624     }
08625 }
08626 
08627 bool sRef_isLocalVar (sRef s)  
08628 {
08629   if (sRef_isValid(s))
08630     {
08631       return (s->kind == SK_CVAR 
08632               && (s->info->cvar->lexlevel > fileScope));
08633     }
08634   
08635   return FALSE;
08636 }
08637 
08638 bool sRef_isRealLocalVar (sRef s)  
08639 {
08640   if (sRef_isValid(s))
08641     {
08642       if (s->kind == SK_CVAR)
08643         {
08644           if (s->info->cvar->lexlevel == functionScope)
08645             {
08646               uentry ue = sRef_getUentry (s);
08647 
08648               if (uentry_isAnyParam (ue)
08649                   || uentry_isRefParam (ue))
08650                 {
08651                   return FALSE;
08652                 }
08653               else
08654                 {
08655                   return TRUE;
08656                 }
08657             }
08658           else
08659             {
08660               return (s->info->cvar->lexlevel > functionScope);
08661             }
08662         }
08663     }
08664   
08665   return FALSE;
08666 }
08667 
08668 bool sRef_isLocalParamVar (sRef s)  
08669 {
08670   if (sRef_isValid(s))
08671     {
08672       return (s->kind == SK_PARAM
08673               || (s->kind == SK_CVAR 
08674                   && (s->info->cvar->lexlevel > fileScope)));
08675     }
08676   
08677   return FALSE;
08678 }
08679 
08680 static speckind speckind_fromInt (int i)
08681 {
08682   /*@+enumint@*/ 
08683   llassert (i >= SR_NOTHING && i <= SR_SYSTEM); 
08684   /*@=enumint@*/
08685 
08686   return ((speckind) i);
08687 }
08688 
08689 void sRef_combineNullState (/*@notnull@*/ sRef res, /*@notnull@*/ sRef other)
08690 {
08691   nstate n1 = res->nullstate;
08692   nstate n2 = other->nullstate;
08693   bool flip = FALSE;
08694   nstate nn = n1;
08695 
08696   if (n1 == n2 || n2 == NS_UNKNOWN)
08697     {
08698       ;
08699     }
08700   else
08701     {
08702       /* note: n2 is not unknown or defnull */
08703 
08704       switch (n1)
08705         {
08706         case NS_ERROR:   nn = NS_ERROR; break;
08707         case NS_UNKNOWN: flip = TRUE; nn = n2; break; 
08708         case NS_POSNULL: break;
08709         case NS_DEFNULL: nn = NS_POSNULL; break;
08710         case NS_RELNULL: break;
08711         case NS_NOTNULL:  
08712           if (n2 == NS_MNOTNULL)
08713             {
08714               ;
08715             }
08716           else 
08717             { 
08718               flip = TRUE;
08719               nn = NS_POSNULL; 
08720             }
08721           break;
08722         case NS_MNOTNULL: 
08723           if (n2 == NS_NOTNULL) 
08724             {
08725               nn = NS_NOTNULL; 
08726             }
08727           else 
08728             {
08729               flip = TRUE;
08730               nn = NS_POSNULL; 
08731             }
08732           break;
08733         case NS_CONSTNULL:
08734         case NS_ABSNULL:
08735           flip = TRUE;
08736           nn = n2;
08737         }
08738     }
08739   
08740   if (flip)
08741     {
08742       res->nullinfo = alinfo_update (res->nullinfo, other->nullinfo);      
08743     }
08744 
08745   res->nullstate = nn;
08746 }
08747 
08748 cstring sRef_nullMessage (sRef s)
08749 {
08750   llassert (sRef_isValid (s));
08751 
08752   switch (s->nullstate)
08753     {
08754     case NS_DEFNULL:
08755     case NS_CONSTNULL:
08756       return (cstring_makeLiteralTemp ("null"));
08757     default:
08758       return (cstring_makeLiteralTemp ("possibly null"));
08759     }
08760   BADEXIT;
08761 }
08762 
08763 sRef sRef_fixResultType (/*@returned@*/ sRef s, ctype typ, uentry ue)
08764 {
08765   sRef tmp = sRef_undefined;
08766   sRef ret;
08767 
08768   llassert (sRef_isValid (s));
08769 
08770   switch (s->kind)
08771     {
08772     case SK_RESULT:
08773       s->type = typ;
08774       ret = s;
08775       break;
08776     case SK_ARRAYFETCH:
08777       {
08778         ctype ct;
08779         tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
08780 
08781         ct = ctype_realType (sRef_getType (tmp));
08782 
08783         
08784         if (ctype_isKnown (ct))
08785           {
08786             if (ctype_isAP (ct))
08787               {
08788                 ;
08789               }
08790             else
08791               {
08792                 voptgenerror 
08793                   (FLG_TYPE,
08794                    message
08795                    ("Special clause indexes non-array (%t): *%q",
08796                     ct, sRef_unparse (s->info->arrayfetch->arr)),
08797                    uentry_whereLast (ue));
08798               }
08799           }
08800 
08801         tmp = sRef_fixResultType (s->info->arrayfetch->arr, typ, ue);
08802 
08803         if (s->info->arrayfetch->indknown)
08804           {
08805             ret = sRef_makeArrayFetchKnown (tmp, s->info->arrayfetch->ind);
08806           }
08807         else
08808           {
08809             ret = sRef_makeArrayFetch (tmp);
08810           }
08811       }
08812       break;
08813     case SK_FIELD:
08814       {
08815         sRef rec = sRef_fixResultType (s->info->field->rec, typ, ue);
08816         ctype ct = ctype_realType (sRef_getType (rec));
08817 
08818         if (ctype_isKnown (ct))
08819           {
08820             if (ctype_isSU (ct))
08821               {
08822                 if (uentry_isValid (uentryList_lookupField (ctype_getFields (ct), 
08823                                                             s->info->field->field)))
08824                   {
08825                     ;
08826                   }
08827                 else
08828                   {
08829                     voptgenerror 
08830                       (FLG_TYPE,
08831                        message
08832                        ("Special clause accesses non-existent field of result: %q.%s",
08833                         sRef_unparse (rec), s->info->field->field),
08834                        uentry_whereLast (ue));
08835                   }
08836               }
08837             else
08838               {
08839                 voptgenerror 
08840                   (FLG_TYPE,
08841                    message
08842                    ("Special clause accesses field of non-struct or union result (%t): %q.%s",
08843                     ct, sRef_unparse (rec), s->info->field->field),
08844                    uentry_whereLast (ue));
08845               }
08846           }
08847         
08848         ret = sRef_makeField (tmp, s->info->field->field);
08849         break;
08850       }
08851     case SK_PTR:
08852       {
08853         ctype ct;
08854         tmp = sRef_fixResultType (s->info->ref, typ, ue);
08855 
08856         ct = ctype_realType (sRef_getType (tmp));
08857 
08858         if (ctype_isKnown (ct))
08859           {
08860             if (ctype_isAP (ct))
08861               {
08862                 ;
08863               }
08864             else
08865               {
08866                 voptgenerror 
08867                   (FLG_TYPE,
08868                    message
08869                    ("Special clause dereferences non-pointer (%t): *%q",
08870                     ct, sRef_unparse (s->info->ref)),
08871                    uentry_whereLast (ue));
08872               }
08873           }
08874         
08875         ret = sRef_makePointer (tmp);
08876         break;
08877       }
08878     case SK_ADR:
08879       voptgenerror 
08880         (FLG_TYPE,
08881          message
08882          ("Special clause uses & operator (not allowed): &%q", sRef_unparse (s->info->ref)),
08883          uentry_whereLast (ue));
08884       ret = s;
08885       break;
08886     BADDEFAULT;
08887     }
08888 
08889   return ret;
08890 }
08891 
08892 bool sRef_isOnly (sRef s)
08893 {
08894   return (sRef_isValid(s) && alkind_isOnly (s->aliaskind));
08895 }
08896 
08897 bool sRef_isDependent (sRef s) 
08898 {
08899   return (sRef_isValid(s) && alkind_isDependent (s->aliaskind));
08900 }
08901 
08902 bool sRef_isOwned (sRef s)
08903 {
08904   return (sRef_isValid (s) && (s->aliaskind == AK_OWNED));
08905 }
08906 
08907 bool sRef_isKeep (sRef s) 
08908 {
08909   return (sRef_isValid (s) && (s->aliaskind == AK_KEEP));
08910 }
08911 
08912 bool sRef_isTemp (sRef s)
08913 {
08914   return (sRef_isValid (s) && alkind_isTemp (s->aliaskind));
08915 }
08916 
08917 bool sRef_isLocalState (sRef s) 
08918 {
08919   return (sRef_isValid (s) && (s->aliaskind == AK_LOCAL));
08920 }
08921 
08922 bool sRef_isUnique (sRef s)
08923 {
08924   return (sRef_isValid (s) && (s->aliaskind == AK_UNIQUE));
08925 }
08926 
08927 bool sRef_isShared (sRef s) 
08928 {
08929   return (sRef_isValid (s) && (s->aliaskind == AK_SHARED));
08930 }
08931 
08932 bool sRef_isExposed (sRef s) 
08933 {
08934   return (sRef_isValid (s) && (s->expkind == XO_EXPOSED));
08935 }
08936 
08937 bool sRef_isObserver (sRef s) 
08938 {
08939   return (sRef_isValid (s) && (s->expkind == XO_OBSERVER));
08940 }
08941 
08942 bool sRef_isFresh (sRef s) 
08943 {
08944   return (sRef_isValid (s) && (s->aliaskind == AK_FRESH));
08945 }
08946 
08947 bool sRef_isDefinitelyNull (sRef s) 
08948 {
08949   return (sRef_isValid (s) && (s->nullstate == NS_DEFNULL 
08950                                || s->nullstate == NS_CONSTNULL));
08951 }
08952 
08953 bool sRef_isAllocated (sRef s)
08954 {
08955   return (sRef_isValid (s) && (s->defstate == SS_ALLOCATED));
08956 }
08957 
08958 bool sRef_isStack (sRef s)
08959 {
08960   return (sRef_isValid (s) && (s->aliaskind == AK_STACK));
08961 }
08962 
08963 extern bool sRef_isNotNull (sRef s)
08964 {
08965   return (sRef_isValid(s) && (s->nullstate == NS_MNOTNULL 
08966                               || s->nullstate == NS_NOTNULL));
08967 }
08968 
08969 
08970 
08971 
08972 
08973 

Generated at Fri Nov 3 18:57:44 2000 for LCLint by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000