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

usymtab.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 ** usymtab
00026 **
00027 ** Lexically scoped symbol table.
00028 **
00029 ** Unlike a normal symbol table, this table splits to reflect branches.
00030 **
00031 ** This is necessary since symbol table entries also reflect
00032 ** some state information, like initialization, that may be
00033 ** different on different branches.
00034 **
00035 ** For each control structure we split:
00036 **
00037 ** { }                - a normal scope (no control) US_NORMAL
00038 **
00039 ** if <pred> { }      - US_TBRANCH true branch
00040 ** while <pred> { }     US_FBRANCH else branch
00041 **
00042 ** switch <pred> { }  - US_SWITCH
00043 **
00044 ** case x:            - case scope US_CBRANCH
00045 **                      Should be kept in a separate table, because of
00046 **                      weird C syntax.
00047 */
00048 
00049 # include "lclintMacros.nf"
00050 # include "basic.h"
00051 # include "structNames.h"
00052 # include "exprChecks.h"
00053 # include "aliasChecks.h"
00054 
00055 /*
00056 ** Keep track of type definitions inside a function.
00057 */
00058 
00059 static uentryList functypes = uentryList_undefined;
00060 
00061 static bool dbgfree = FALSE;
00062 static bool dbgload = TRUE;
00063 
00064 /*@access ekind usymId@*/
00065 
00066 /*
00067 ** Hack to prevent shadow errors from appearing when function parameters
00068 ** are entered into a new scope.
00069 */
00070 
00071 static bool noshadowerror = FALSE;
00072 
00073 /*
00074 ** Constraint: static variables can live in 1 or > 2. 
00075 **
00076 ** except for tags.  All tags must be at the global level.
00077 ** Static tags are handled in a kludgey way.
00078 */
00079 
00080 /*
00081 ** utab    is the universal symbol table
00082 ** globtab is the global environment of utab
00083 ** oldtab  is needed for conversions in dumping (after sorting the table)
00084 **
00085 ** there can be only one usymtab!
00086 */
00087 
00088 static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
00089 
00090 /* Reachable environments from from utab */
00091 static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
00092 static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
00093 
00094 /* Used for sorting for dumpage. */
00095 static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
00096 
00097 static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
00098 static bool usymtab_isProbableNullAltBranch (sRef p_s) /*@globals utab@*/ ;
00099 static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
00100 static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
00101 
00102 static void
00103 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
00104   /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
00105 
00106 static bool usymtab_isProbableNullAux (sRef p_s) /*@globals utab@*/ ;
00107 static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
00108 static /*@exposed@*/ /*@dependent@*/ uentry 
00109   usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
00110 static /*@unused@*/ /*@only@*/ cstring 
00111   usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
00112 static /*@unused@*/ /*@only@*/ cstring 
00113   usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
00114 static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
00115 static void usymtab_handleParams (void)
00116    /*@globals utab, globtab, filetab@*/ 
00117    /*@modifies utab@*/ ;
00118 
00119 static /*@exposed@*/ /*@dependent@*/ uentry 
00120   usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
00121 static /*@exposed@*/ /*@dependent@*/ usymtab
00122   usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
00123 static /*@exposed@*/ /*@dependent@*/ uentry 
00124   usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
00125 
00126 static /*@exposed@*/ /*@dependent@*/ uentry 
00127   usymtab_lookupQuiet (usymtab p_s, cstring p_k);
00128 static void usymtab_printAllAux (usymtab p_s) /*@modifies g_msgstream@*/ ;
00129 static int usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
00130 static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, int p_i);
00131 static /*@exposed@*/ uentry 
00132   usymtab_lookupAux (usymtab p_s, cstring p_k);
00133 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/ usymtab 
00134   usymtab_getFileTab (void) /*@globals filetab@*/ ;
00135 static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, int p_index);
00136 static bool usymtab_mustBreak (usymtab p_s);
00137 static bool usymtab_mustEscape (usymtab p_s);
00138 
00139 static void recordFunctionType (uentry ue)
00140 {
00141     llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
00142             || uentry_isEnumConstant (ue));
00143 
00144   /*@-temptrans@*/
00145   functypes = uentryList_add (functypes, ue);
00146   /*@=temptrans@*/
00147 }
00148 
00149 static void clearFunctionTypes (void)
00150   /*@modifies globtab@*/
00151 {
00152   uentryList_elements (functypes, el)
00153     {
00154       if (cstring_isDefined (uentry_rawName (el)))
00155         {
00156           if (globtab->htable != NULL)
00157             {
00158               hashTable_remove (globtab->htable, uentry_rawName (el));
00159             }
00160 
00161           uentry_setName (el, cstring_undefined);
00162         }
00163 
00164       /*@access uentry@*/ 
00165       llassert (uentry_isValid (el));
00166       el->sref = sRef_undefined;
00167       /*@noaccess uentry@*/
00168     } end_uentryList_elements ;
00169 
00170   uentryList_clear (functypes);
00171 }
00172 
00173 static /*@falsenull@*/ bool usymtab_isBranch (usymtab u)
00174 {
00175   return (usymtab_isDefined (u) && 
00176           (u->kind == US_TBRANCH || u->kind == US_FBRANCH
00177            || u->kind == US_CBRANCH || u->kind == US_SWITCH));
00178 }
00179 
00180 static bool usymtab_mustBreak (usymtab s)
00181 {
00182   llassert (s != GLOBAL_ENV);
00183   return (s->mustBreak);
00184 }
00185 
00186 static bool usymtab_mustEscape (usymtab s)
00187 {
00188   llassert (s != GLOBAL_ENV);
00189   return (exitkind_mustEscape (s->exitCode));
00190 }
00191 
00192 void usymtab_setMustBreak () 
00193   /*@modifies utab@*/
00194 {
00195   llassert (utab != GLOBAL_ENV);
00196   utab->mustBreak = TRUE;
00197 }
00198 
00199 void usymtab_setExitCode (exitkind ex) 
00200    /*@modifies utab@*/
00201 {
00202   llassert (utab != GLOBAL_ENV);
00203 
00204   utab->exitCode = ex;
00205   
00206   if (exitkind_mustEscape (ex))
00207     {
00208       utab->mustBreak = TRUE;
00209     }
00210 }
00211 
00212 bool usymtab_isAltProbablyDeepNull (sRef s)
00213 {
00214   return (sRef_deepPred (usymtab_isProbableNullAltBranch, s));
00215 }
00216 
00217 static bool usymtab_isProbableNullAltBranch (sRef s) 
00218    /*@globals utab@*/
00219 {
00220   guardSet t;
00221   bool res;
00222 
00223   t = utab->guards;
00224 
00225   llassert (utab->env != NULL);
00226 
00227   /*@-mods@*/ /* These modifications are cancelled. */
00228   utab->guards = utab->env->guards;
00229   utab->env->guards = t;
00230   /*@=mods@*/
00231 
00232   llassert (usymtab_isDefined (utab));
00233   res = usymtab_isProbableNull (s);
00234 
00235   /*
00236   ** This reports a spurious error.  It is okay, because of
00237   ** the nesting relationship of usymtab environments.
00238   */
00239 
00240   /*@-mods@*/ /* Cancelling modifications. */
00241   /*@i1@*/ utab->env->guards = utab->guards;
00242   /*@i1@*/ utab->guards = t;
00243   /*@=mods@*/ 
00244 
00245   return res;
00246 }
00247 
00248 static /*@notnull@*/ /*@special@*/ usymtab
00249   usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
00250   /*@defines result@*/
00251   /*@post:isnull result->htable, result->guards, result->aliases@*/
00252 {
00253   usymtab t = (usymtab) dmalloc (sizeof (*t));
00254   
00255   t->nentries = 0;
00256   t->nspace = CBASESIZE;
00257   t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
00258   t->reftable = (nextlevel 
00259                  ? NULL
00260                  : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
00261   
00262   t->kind = kind;
00263   t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0); 
00264 
00265   t->env = env;
00266   t->htable = NULL;
00267 
00268   t->guards = guardSet_undefined;
00269   t->aliases = aliasTable_undefined;
00270 
00271     t->mustBreak = FALSE;
00272   t->exitCode = XK_NEVERESCAPE;
00273 
00274   return t;
00275 }
00276 
00277 /*
00278 ** constructors
00279 */
00280 
00281 static /*@only@*/ /*@notnull@*/ usymtab
00282   usymtab_createRoot (void) /*@modifies nothing@*/
00283 {
00284   usymtab u = (usymtab) dmalloc (sizeof (*u));
00285   
00286   u->nentries = 0;
00287   u->nspace = CGLOBBASESIZE;
00288   u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
00289   u->env = GLOBAL_ENV;
00290   u->lexlevel = 0;
00291   u->htable = hashTable_create (CGLOBHASHSIZE);
00292   u->reftable = NULL;
00293 
00294   u->guards = guardSet_new ();
00295   u->aliases = aliasTable_new ();
00296 
00297   u->mustBreak = FALSE;
00298   u->exitCode = XK_NEVERESCAPE;
00299   u->kind = US_NORMAL;
00300 
00301   return (u);
00302 }
00303 
00304 void
00305 usymtab_initMod (void)
00306    /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
00307    /*@modifies utab, globtab, filetab, oldtab @*/
00308 {
00309   utab = usymtab_createRoot ();
00310   globtab = utab;
00311   filetab = usymtab_undefined;
00312   oldtab = usymtab_undefined;
00313 }
00314 
00315 /*
00316 ** utab should be empty?  (requires?)
00317 **
00318 ** Adds bool types to symbol table (these are built in for now)
00319 ** Only do this is there is no library!
00320 */
00321 
00322 void
00323 usymtab_initBool ()
00324 {
00325   if (context_getFlag (FLG_NOLIB))
00326     {
00327       ctype boolt = ctype_bool;
00328       /* evs 2000-07-24: bool is now treated as abstract (always) */
00329 
00330       uentry boolentry = uentry_makeBoolDatatype (YES);
00331       usymtab_supGlobalEntry (boolentry);
00332       context_addBoolAccess ();
00333 
00334       /*
00335       ** We supply values 0 and 1 for the constants, so things like
00336       ** while (TRUE) can be interpreted correctly.
00337       */
00338 
00339       usymtab_supGlobalEntry 
00340         (uentry_makeConstantAux (context_getFalseName (), boolt, 
00341                                  fileloc_getBuiltin (), FALSE,
00342                                  multiVal_makeInt (0)));
00343       usymtab_supGlobalEntry 
00344         (uentry_makeConstantAux (context_getTrueName (), boolt, 
00345                                  fileloc_getBuiltin (), FALSE,
00346                                  multiVal_makeInt (1)));
00347     }
00348 }
00349 
00350 /*
00351 ** mutators 
00352 */
00353 
00354 static void
00355 usymtab_grow (/*@notnull@*/ usymtab s)
00356 {
00357   int i;
00358   o_uentry *oldsyms = s->entries;
00359 
00360   s->nspace = CBASESIZE;
00361   s->entries = (uentry *) dmalloc (sizeof (*s->entries) 
00362                                    * (s->nentries + s->nspace));
00363 
00364   for (i = 0; i < s->nentries; i++)
00365     {
00366       s->entries[i] = oldsyms[i];
00367     }
00368 
00369   sfree (oldsyms);
00370 
00371   if (s->reftable != NULL)
00372     {
00373       refTable oldRefs = s->reftable;
00374 
00375       s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
00376                                           * (s->nentries + CBASESIZE + 1));
00377       
00378       for (i = 0; i < s->nentries; i++)
00379         {
00380           s->reftable[i] = oldRefs[i];
00381         }
00382 
00383       /*@-compdestroy@*/ 
00384       sfree (oldRefs);
00385       /*@=compdestroy@*/ 
00386     }
00387       
00388 }
00389 
00390 static void
00391 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
00392 {
00393   if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
00394     {
00395       if (uentry_isDatatype (e) 
00396           || uentry_isFunction (e)
00397           || uentry_isAnyTag (e)
00398           || uentry_isEnumConstant (e)
00399           || context_inMacro ())
00400         {
00401           /* 
00402           ** Not a bug.  Code like,
00403           **    int f (void) { typedef int tint; ... }
00404           ** is legal.
00405           */
00406           
00407           /* was nothing here! */
00408           /*@i@*/ e->sref = sRef_saveCopy (e->sref);
00409         }
00410       else
00411         {
00412           llparseerror 
00413             (cstring_makeLiteral ("Declaration outside function scope"));
00414 
00415           llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
00416                               "(lexlevel = %d, modFunction = %s) adding: %q", 
00417                               s->lexlevel, bool_unparse (sRef_modInFunction ()), 
00418                               uentry_unparse (e)));
00419           sRef_setGlobalScope ();
00420           /* make sure the sRef is not bashed! */
00421           /*@i@*/ e->sref = sRef_saveCopy (e->sref);
00422         }
00423     }
00424 
00425   if (s->nspace <= 0)
00426     {
00427       usymtab_grow (s);
00428     }
00429   
00430   s->nspace--;
00431   s->entries[s->nentries] = e;
00432 
00433 # ifdef DOANNOTS
00434   if (s == globtab || s == filetab)
00435     {
00436       if (!fileloc_isLib (g_currentloc))
00437         {
00438           uentry_tallyAnnots (e, AN_UNKNOWN);
00439         }
00440     }
00441 # endif
00442 
00443   if (s->htable != NULL)
00444     {
00445       hashTable_insert (s->htable, uentry_rawName (e), s->nentries);
00446     }
00447 
00448   s->nentries++;
00449 }
00450 
00451 static /*@observer@*/ uentry /*@alt void@*/
00452 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
00453 {
00454   /* 
00455   ** In theory, we shouldn't need this test because it this is
00456   ** only called when a library is being read, and it shouldn't
00457   ** ever have a duplicate entry.  In practice, its safer to
00458   ** leave it in, though.
00459   */
00460 
00461   uentry old;
00462 
00463   if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
00464     {
00465       DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
00466       uentry_free (e); /* duplicate */
00467       return old;
00468     }
00469   else
00470     {
00471       int thisentry = s->nentries;  
00472       
00473       if (uentry_isVar (e))
00474         {
00475           uentry_setSref (e, sRef_makeCvar (globScope, thisentry, 
00476                                             uentry_getType (e)));
00477         }
00478       
00479       usymtab_addEntryQuiet (s, e);
00480       return e;
00481     }
00482 }
00483 
00484 static usymId
00485 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
00486      /*@globals globtab@*/
00487      /*@modifies st, e@*/
00488 {
00489   usymId thisentry = st->nentries;
00490 
00491   llassert (!uentry_isElipsisMarker (e));
00492 
00493   /*
00494   ** not true for tags
00495   **  llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
00496   **/
00497 
00498   llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE, 
00499                  ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
00500 
00501   if (st->lexlevel == fileScope 
00502       && (!(uentry_isStatic (e)) || uentry_isAnyTag (e))) 
00503     {
00504       st = globtab;
00505     }
00506 
00507   if (isSref)
00508     {
00509       ctype ct = uentry_getType (e);
00510 
00511       if (uentry_isFunction (e) && ctype_isFunction (ct))
00512         {
00513           ct = ctype_returnValue (ct);
00514         }
00515 
00516       if (uentry_isStatic (e))
00517         {
00518           sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct);
00519 
00520           if (sRef_isStack (sr) || sRef_isLocalState (sr))
00521             {
00522               sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
00523               sRef_setDefined (sr, uentry_whereLast (e));
00524             }
00525           
00526           uentry_setSref (e, sr);
00527         }
00528       else
00529         {
00530           uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct));
00531         }
00532 
00533           }
00534 
00535   if (uentry_isDatatype (e))
00536     {
00537       
00538       uentry_setDatatype (e, thisentry);
00539     }
00540 
00541   if (uentry_isFunction (e))
00542     {
00543       ctype ct = uentry_getType (e);
00544 
00545       if (ctype_isFunction (ct)
00546           && uentryList_isMissingParams (ctype_argsFunction (ct)))
00547         {
00548           if (uentry_isDeclared (e))
00549             {
00550               voptgenerror 
00551                 (FLG_NOPARAMS,
00552                  message ("Function %q declared without parameter list",
00553                           uentry_getName (e)),
00554                  uentry_whereDeclared (e));
00555             }
00556           else
00557             {
00558               voptgenerror
00559                 (FLG_NOPARAMS,
00560                  message ("Function %q specified without parameter list",
00561                           uentry_getName (e)),
00562                  uentry_whereSpecified (e));
00563             }
00564         }
00565     }
00566 
00567   if (st == globtab && !uentry_isSpecified (e))
00568     {
00569       exprChecks_checkExport (e);
00570     }
00571   
00572   
00573   uentry_checkName (e);
00574   
00575   usymtab_addEntryQuiet (st, e);
00576   return (thisentry);
00577 }
00578 
00579 usymId
00580 usymtab_addEntry (uentry e) 
00581    /*@globals utab, globtab@*/
00582    /*@modifies utab, e@*/
00583 {
00584   
00585   llassertprint (!usymtab_exists (uentry_rawName (e)),
00586                  ("Entry already exists: %s", uentry_unparse (e)));
00587 
00588   return usymtab_addEntryAux (utab, e, FALSE);
00589 }
00590 
00591 void
00592 usymtab_addGlobalEntry (uentry e)
00593    /*@modifies globtab, e@*/ 
00594 {
00595   DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
00596 
00597   (void) usymtab_addEntryAux (globtab, e, FALSE);
00598 }
00599 
00600 /*
00601 ** supercede and replace entry use elements of entries array, and
00602 ** assign an element to a new value, and then free the old value.
00603 ** Need -deparrays to avoid errors for this. 
00604 */
00605 
00606 /*@-deparrays@*/ 
00607 
00608 static usymId
00609 usymtab_supEntryAux (/*@notnull@*/ usymtab st, 
00610                      /*@only@*/ uentry e, bool isSref)
00611    /*@globals globtab, filetab@*/
00612    /*@modifies st, globtab, e@*/
00613 {
00614   cstring ename = uentry_rawName (e);
00615   bool staticEntry = FALSE;
00616   int eindex;
00617 
00618   /* static tags in global scope */
00619   if (st->lexlevel == fileScope 
00620       && (!(uentry_isStatic (e)) || uentry_isAnyTag (e))) 
00621     {
00622       eindex = usymtab_getIndex (st, ename);
00623 
00624       if (eindex != NOT_FOUND)
00625         {
00626           uentry ce = st->entries[eindex];      
00627           
00628           if (optgenerror
00629               (FLG_SHADOW,
00630                message ("%s %q shadows static declaration",
00631                         ekind_capName (uentry_getKind (e)),
00632                         uentry_getName (e)),
00633                uentry_whereDeclared (e)))
00634             {
00635               uentry_showWhereLast (ce);
00636             }
00637 
00638           if (eindex == st->nentries - 1)
00639             {
00640              ;
00641             }
00642           else
00643             {
00644               st->entries[eindex] = st->entries[st->nentries - 1];
00645             }
00646 
00647           if (st->htable != NULL)
00648             {
00649               hashTable_replaceKey (st->htable, uentry_rawName (ce), 
00650                                     uentry_rawName (e));
00651             }
00652 
00653           uentry_free (ce);
00654           st->nentries--;
00655         }
00656       
00657       st = globtab;
00658     }
00659 
00660   if (uentry_isStatic (e)) {
00661     if (uentry_isFunction (e)) {
00662       /* Static function declarations are at the file level, even if they are in a deeped scope. */
00663       st = usymtab_getFileTab ();
00664       staticEntry = TRUE;
00665     } else {
00666       if (!uentry_isAnyTag (e) && st == globtab) 
00667         {
00668           st = usymtab_getFileTab ();
00669           staticEntry = TRUE;
00670           DPRINTF (("Static entry!"));
00671         }
00672     }
00673   }
00674 
00675   DPRINTF (("Using symtab: %s", usymtab_unparseLocalAux (st)));
00676 
00677   eindex = usymtab_getIndex (st, ename);
00678       
00679   if (eindex != NOT_FOUND)
00680     {
00681       uentry ce = st->entries[eindex];
00682 
00683       DPRINTF (("Found entry: %s", uentry_unparse (ce)));
00684 
00685       if (uentry_isPriv (ce)
00686           /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
00687           || (uentry_isStatic (ce) 
00688               && uentry_isAnyTag (ce)
00689               && (uentry_isDeclared (ce) 
00690                   && !fileloc_sameFile (uentry_whereDefined (ce),
00691                                         uentry_whereDefined (e)))))
00692         {
00693           /*
00694           ** overload entry 
00695           **    if overloading import should do some checks!
00696           */
00697 
00698           llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
00699           
00700           st->entries[eindex] = e;
00701 
00702           if (uentry_isDatatype (e))
00703             {
00704               uentry_setDatatype (e, eindex);
00705             }
00706           
00707           if (st == globtab && !uentry_isSpecified (e))
00708             {
00709               exprChecks_checkExport (e);
00710             }
00711 
00712           if (st->htable != NULL)
00713             {
00714               hashTable_replaceKey (st->htable, uentry_rawName (ce), 
00715                                     uentry_rawName (e));
00716             }
00717 
00718           uentry_free (ce);
00719           ce = e; 
00720         }
00721       else if (uentry_isSpecified (ce))
00722         {
00723           if (uentry_isSpecified (e))
00724             {
00725               if (fileloc_isImport (uentry_whereSpecified (ce)))
00726                 {
00727                   
00728                   if (st->htable != NULL)
00729                     {
00730                       hashTable_replaceKey (st->htable, 
00731                                             uentry_rawName (ce), 
00732                                             uentry_rawName (e));
00733                     }
00734                   
00735                   uentry_free (ce); 
00736                   st->entries[eindex] = e;
00737                   ce = e;
00738 
00739                   if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
00740                 }
00741               else 
00742                 {
00743                   if (fileloc_isImport (uentry_whereSpecified (e)))
00744                     {
00745                       uentry_free (e);
00746                     }
00747                   else
00748                     {
00749                       /* respecification errors already reported */
00750   
00751                       if (uentry_isDatatype (e)) 
00752                         {
00753                           uentry_setDatatype (e, eindex);
00754                         }
00755                       
00756                       if (st->htable != NULL)
00757                         {
00758                           hashTable_replaceKey (st->htable, 
00759                                                 uentry_rawName (ce), 
00760                                                 uentry_rawName (e));
00761                         }
00762                       
00763                       llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
00764                       uentry_free (ce);
00765                       st->entries[eindex] = e;
00766                       ce = e;
00767                     } 
00768                 }
00769             }
00770           else /* e not specified */
00771             {
00772               if (uentry_isDeclared (ce))
00773                 {
00774                   llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
00775                   uentry_mergeDefinition (ce, e);
00776                 }
00777               else 
00778                 {
00779                   llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
00780                   uentry_mergeEntries (ce, e);
00781                 }
00782             }
00783         }
00784       else /* ce not specified */
00785         {
00786           if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
00787             {
00788               if (uentry_isDatatype (e) || uentry_isAnyTag (e)
00789                   || uentry_isEnumConstant (e))
00790                 {
00791                   ; /* 
00792                      ** Not a bug.  Code like,
00793                      **    int f (void) { typedef int tint; ... }
00794                      ** is legal.
00795                      */
00796                 }
00797               else
00798                 {
00799                   llcontbug (message ("usymtab_supEntryAux: inconsistent state "
00800                                       "(lexlevel = %d, modFunction = %s) adding: %q", 
00801                                       st->lexlevel, bool_unparse (sRef_modInFunction ()), 
00802                                       uentry_unparse (e)));
00803 
00804                   if (sRef_modInFunction ())
00805                     {
00806                       /* make sure the sRef is not bashed! */
00807                       /*@i@*/ e->sref = sRef_saveCopy (e->sref);
00808                     }
00809                 }
00810             }
00811           
00812           uentry_mergeDefinition (ce, e);
00813         }
00814       
00815       if (isSref)
00816         {
00817           ctype ct = uentry_getType (ce);
00818           
00819           if (uentry_isFunction (ce) && ctype_isFunction (ct))
00820             {
00821               ct = ctype_returnValue (ct);
00822             }
00823           
00824           uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct));
00825                 }
00826     }
00827   else /* no previous entry */
00828     {
00829       uentry outer;
00830 
00831       if (st->lexlevel == globScope 
00832           && !uentry_isStatic (e)
00833           && !uentry_isExtern (e)
00834           && usymtab_isDefined (filetab))
00835         {
00836           /*
00837           ** check if there is a static entry:  (i.e.,
00838           **   
00839           **    static int f ();
00840           **    ...
00841           **    int f (); 
00842           */
00843           
00844           eindex = usymtab_getIndex (filetab, ename);
00845           
00846           if (eindex != NOT_FOUND)
00847             {
00848               uentry ce = filetab->entries[eindex];
00849 
00850               uentry_setStatic (e);
00851               uentry_mergeDefinition (ce, e);
00852               staticEntry = TRUE;
00853               goto exitPoint;
00854             }
00855         }
00856       
00857       outer = usymtab_lookupQuiet (st->env, ename);
00858 
00859       /*
00860       ** no previous definition, add the new one
00861       */
00862       
00863       if (!noshadowerror 
00864           && uentry_isValid (outer)
00865           && !(uentry_isYield (e) || uentry_isYield (outer))
00866           && fileloc_isDefined (uentry_whereLast (e))
00867           && fileloc_isDefined (uentry_whereLast (outer)))
00868         {
00869           if (!uentry_sameKind (outer, e))
00870             {
00871               ; /* no error */
00872             }
00873           else
00874             {
00875               if (ctype_isUnknown (uentry_getType (outer))
00876                   || uentry_isForward (outer))
00877                 {
00878                   ;
00879                 }
00880               else
00881                 {
00882                   if (optgenerror 
00883                       (FLG_SHADOW,
00884                        message ("%s %q shadows outer declaration",
00885                                 ekind_capName (uentry_getKind (e)),
00886                                 uentry_getName (e)),
00887                        uentry_whereLast (e)))
00888                     {
00889                       uentry_showWhereLast (outer);
00890                     }
00891                 }
00892             }
00893         }
00894       
00895       if (st == globtab && context_getFlag (FLG_NEWDECL))
00896         {
00897           voptgenerror 
00898             (FLG_NEWDECL,
00899              message ("New declaration: %q", uentry_getName (e)),
00900              uentry_whereLast (e));
00901         }
00902 
00903       eindex = usymtab_addEntryAux (st, e, isSref);
00904     }
00905 
00906  exitPoint:
00907     return (staticEntry ? USYMIDINVALID : eindex);
00908 }
00909 
00910 # ifndef NOLCL
00911 static void
00912 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
00913    /*@globals globtab@*/ /*@modifies st, e@*/
00914 {
00915   cstring ename = uentry_rawName (e);
00916   int eindex;
00917 
00918   /* static tags in global scope */
00919   eindex = usymtab_getIndex (st, ename);
00920   
00921   if (eindex != NOT_FOUND)
00922     {
00923       uentry ce = st->entries[eindex];      
00924       
00925       if (st->htable != NULL)
00926         {
00927           hashTable_replaceKey (st->htable, uentry_rawName (ce), uentry_rawName (e));
00928         }
00929 
00930       uentry_free (ce);
00931       st->entries[eindex] = e;
00932     }
00933   else
00934     {
00935       eindex = usymtab_addEntryAux (st, e, FALSE);
00936     }
00937 }
00938 # endif
00939 
00940 /*@=deparrays@*/ 
00941 
00942 void usymtab_supEntry (uentry e)
00943    /*@globals utab, filetab, globtab@*/
00944    /*@modifies utab, globtab, e@*/
00945 {
00946     (void) usymtab_supEntryAux (utab, e, FALSE);
00947 }
00948 
00949 /*
00950 ** this should be lots more efficient!
00951 */
00952 
00953 static /*@exposed@*/ uentry 
00954   usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab, 
00955                              /*@only@*/ uentry e, bool isref)
00956   /*@globals globtab, filetab@*/
00957   /*@modifies tab, globtab, e@*/
00958 {
00959   cstring rawName = cstring_copy (uentry_rawName (e));
00960   bool stat = (tab == globtab) && uentry_isStatic (e);
00961   uentry ret;
00962 
00963     
00964   (void) usymtab_supEntryAux (tab, e, isref);
00965 
00966   if (stat)
00967     {
00968       ret = usymtab_lookupAux (filetab, rawName);
00969     }
00970   else
00971     {
00972       ret = usymtab_lookupAux (tab, rawName);
00973 
00974       if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
00975         {
00976           ret = usymtab_lookupAux (filetab, rawName);
00977         }
00978     }
00979   
00980   cstring_free (rawName);
00981   return ret;
00982 }
00983 
00984 /*@dependent@*/ /*@exposed@*/ uentry 
00985   usymtab_supEntryReturn (/*@only@*/ uentry e)
00986   /*@globals utab, filetab, globtab@*/
00987   /*@modifies utab, globtab, e@*/
00988 {
00989   return (usymtab_supEntryReturnAux (utab, e, FALSE));
00990 }
00991 
00992 /*@dependent@*/ /*@exposed@*/ uentry 
00993   usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
00994   /*@globals utab, globtab, filetab@*/
00995   /*@modifies utab, globtab, e@*/
00996 {
00997   return (usymtab_supEntryReturnAux (utab, e, TRUE));
00998 }
00999 
01000 /*@dependent@*/ /*@exposed@*/ uentry 
01001   usymtab_supGlobalEntryReturn (uentry e)
01002   /*@globals globtab, filetab@*/
01003   /*@modifies globtab, e@*/
01004 {
01005   uentry ret;
01006 
01007   ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
01008 
01009   if (sRef_modInFunction ())
01010     {
01011       recordFunctionType (ret);
01012     }
01013 
01014   return (ret);
01015 }
01016 
01017 ctype
01018 usymtab_supTypeEntry (/*@only@*/ uentry e)
01019   /*@globals globtab, filetab@*/
01020   /*@modifies globtab, e@*/
01021 {
01022   usymId uid;
01023   ctype ret;
01024 
01025   if (uentry_isAbstractDatatype (e))
01026     {
01027       uid = usymtab_supAbstractTypeEntry (e, FALSE);
01028       ret = ctype_createAbstract (uid);
01029     }
01030   else
01031     {
01032       uid = usymtab_supEntryAux (globtab, e, FALSE);
01033       ret = ctype_createUser (uid);
01034     }
01035 
01036   if (sRef_modInFunction ())
01037     {
01038       recordFunctionType (globtab->entries[uid]);
01039     }
01040 
01041   return ret;
01042 }
01043 
01044 uentry
01045 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
01046   /*@globals globtab, filetab@*/
01047   /*@modifies globtab@*/
01048 {
01049   usymId uid;
01050   
01051   if (uentry_isAbstractDatatype (e))
01052     {
01053       uid = usymtab_supAbstractTypeEntry (e, FALSE);
01054     }
01055   else
01056     {
01057       uid = usymtab_supEntryAux (globtab, e, FALSE);
01058     }
01059   
01060   if (sRef_modInFunction ())
01061     {
01062       recordFunctionType (globtab->entries[uid]);
01063     }
01064 
01065     return (globtab->entries[uid]);
01066 }
01067 
01068 usymId
01069 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
01070   /*@globals globtab, filetab@*/
01071   /*@modifies globtab, e@*/
01072 {
01073   usymId uid;
01074   uid = usymtab_supEntryAux (globtab, e, FALSE);
01075 
01076   if (dodef)
01077     {
01078       uentry ue = usymtab_getTypeEntry (uid);
01079       uentry_setDatatype (ue, uid);
01080     }
01081 
01082   if (context_getFlag (FLG_ACCESSMODULE))
01083     {
01084       context_addFileAccessType (uid);
01085     }
01086 
01087   if (sRef_modInFunction ())
01088     {
01089       recordFunctionType (globtab->entries[uid]);
01090     }
01091 
01092   return (uid);
01093 }
01094 
01095 # ifndef NOLCL
01096 usymId
01097 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
01098   /*@globals globtab, filetab@*/
01099   /*@modifies globtab, e@*/
01100 {
01101   usymId uid;
01102 
01103   uid = usymtab_supEntryAux (globtab, e, FALSE);
01104 
01105   if (dodef)
01106     {
01107       uentry ue = usymtab_getTypeEntry (uid);
01108 
01109       uentry_setDatatype (ue, uid);
01110     }
01111 
01112   if (sRef_modInFunction ())
01113     {
01114       recordFunctionType (globtab->entries[uid]);
01115     }
01116 
01117   return (uid);
01118 }
01119 # endif
01120 
01121 ctype
01122 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
01123   /*@globals globtab, filetab@*/
01124   /*@modifies globtab, e@*/
01125 {
01126   usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
01127   uentry ue = usymtab_getTypeEntry (uid);
01128 
01129     uentry_setDatatype (ue, uid);
01130 
01131   if (sRef_modInFunction ())
01132     {
01133       recordFunctionType (globtab->entries[uid]);
01134     }
01135 
01136   return (uentry_getAbstractType (ue));
01137 }
01138 
01139 void
01140   usymtab_supEntrySref (uentry e)
01141   /*@globals utab, globtab, filetab@*/
01142   /*@modifies utab, globtab, e@*/
01143 {
01144   sRef old = uentry_getSref (e);
01145 
01146   
01147   if (sRef_isType (old))
01148     {
01149       uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
01150 
01151       /*@access uentry@*/
01152       if (uentry_isValid (ue)) 
01153         {
01154           sRef uref = uentry_getSref (ue);
01155 
01156           sRef_mergeStateQuiet (uref, old); 
01157           sRef_clearDerived (uref);
01158         }
01159       /*@noaccess uentry@*/
01160     }
01161   else if (sRef_isKnown (old))
01162     {
01163       usymtab_supEntry (e);
01164     }
01165   else
01166     {
01167       (void) usymtab_supEntryAux (utab, e, TRUE);
01168     }
01169 }
01170 
01171 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
01172   /*@globals globtab, filetab@*/
01173   /*@modifies globtab, filetab, e@*/
01174 {
01175   usymId uid;
01176 
01177   DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
01178 
01179   uid = usymtab_supEntryAux (globtab, e, FALSE);
01180 
01181   if (sRef_modInFunction ())
01182     {
01183       recordFunctionType (globtab->entries[uid]);
01184     }
01185 }
01186 
01187 uentry
01188   usymtab_supReturnFileEntry (/*@only@*/ uentry e)
01189   /*@globals filetab, globtab@*/
01190   /*@modifies filetab, globtab, e@*/
01191 {
01192   llassert (filetab != usymtab_undefined);
01193   DPRINTF (("File entry: %s", uentry_unparse (e)));
01194   return (usymtab_supEntryReturnAux (filetab, e, FALSE));
01195 }
01196 
01197 /*
01198 ** observers
01199 */
01200 
01201 bool
01202 usymtab_inDeepScope () /*@globals utab@*/
01203 {
01204   return (utab->lexlevel > paramsScope);
01205 }
01206 
01207 static int
01208 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
01209 {
01210   int i;
01211 
01212   if (s->htable != NULL)
01213     {
01214       i = hashTable_lookup (s->htable, k);
01215 
01216       return i;
01217     }
01218   else
01219     {
01220       for (i = 0; i < s->nentries; i++)
01221         {
01222           uentry current = s->entries[i];
01223 
01224           if (!uentry_isUndefined (current) 
01225               && cstring_equal (uentry_rawName (current), k))
01226             {
01227               return i;
01228             }
01229         }
01230 
01231       return NOT_FOUND;
01232     }
01233 }
01234 
01235 static uentry
01236 usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
01237 {
01238   llassert (i >= 0 && i < s->nentries);
01239   return (s->entries[i]);
01240 }
01241 
01242 usymId
01243 usymtab_getTypeId (cstring k) /*@globals globtab@*/
01244 {
01245   usymId uid = usymtab_getIndex (globtab, k);
01246 
01247   if (uid == NOT_FOUND) return USYMIDINVALID;
01248 
01249   if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
01250     return USYMIDINVALID;
01251   }
01252 
01253   return uid;
01254 }
01255 
01256 /*@dependent@*/ uentry
01257 usymtab_lookupStructTag (cstring k)
01258 {
01259   cstring sname = makeStruct (k);
01260   uentry ue = usymtab_lookupGlob (sname);
01261     cstring_free (sname);
01262   return (ue);
01263 }
01264 
01265 /*@dependent@*/ uentry
01266 usymtab_lookupUnionTag (cstring k)
01267 {
01268   cstring uname = makeUnion (k);
01269   uentry res = usymtab_lookupGlob (uname);
01270 
01271   cstring_free (uname);
01272   return res;
01273 }
01274 
01275 /*@dependent@*/ uentry
01276 usymtab_lookupEnumTag (cstring k)
01277 {
01278   cstring ename = makeEnum (k);
01279   uentry res = usymtab_lookupGlob (ename);
01280 
01281   cstring_free (ename);
01282   return res;
01283 }
01284 
01285 usymId
01286 usymtab_getId (cstring k) /*@globals globtab@*/
01287 {
01288   usymId uid = usymtab_getIndex (globtab, k);
01289   uentry ue;
01290 
01291   if (uid == NOT_FOUND)
01292     {
01293       return USYMIDINVALID;
01294     }
01295 
01296   ue = usymtab_getGlobalEntry (uid);
01297 
01298   if (uentry_isPriv (ue))
01299     {
01300       return USYMIDINVALID;
01301     }
01302 
01303   return uid;
01304 }
01305 
01306 static /*@exposed@*/ uentry 
01307 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
01308 {
01309   llassert (uid != USYMIDINVALID);
01310  
01311   if (uid < 0 || uid >= s->nentries)
01312     {
01313       llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
01314                           s->lexlevel, uid));
01315       return uentry_undefined;
01316     }
01317 
01318   llassertprint (uentry_isValid (s->entries[uid]),
01319                  ("entry undefined: %d", uid));
01320 
01321   return s->entries[uid];
01322 }
01323 
01324 /*@dependent@*/ /*@observer@*/ uentry 
01325   usymtab_getGlobalEntry (usymId uid)
01326   /*@globals utab, globtab@*/
01327 {
01328   if (dbgfree) return (uentry_undefined);
01329   
01330   if (utab->lexlevel > paramsScope)
01331     {
01332       /* need to do this the awkward way, since it could be in conditional scope */
01333      return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
01334     }
01335   else
01336     {
01337       return (globtab->entries[uid]);
01338     }
01339 }
01340 
01341 /*@dependent@*/ /*@exposed@*/ uentry 
01342   usymtab_getTypeEntry (usymId uid)
01343   /*@globals globtab@*/
01344 {
01345   if (dbgload)
01346     {
01347       if (uid >= 0 && uid < globtab->nentries)
01348         {
01349           return (globtab->entries[uid]);
01350         }
01351       else
01352         {
01353           return (uentry_undefined);
01354         }
01355     }
01356   else
01357     {
01358       llassert (uid >= 0 && uid < globtab->nentries);
01359       
01360       return (globtab->entries[uid]);
01361     }
01362 }
01363 
01364 /*
01365 ** in load files
01366 */
01367 
01368 /*@dependent@*/ /*@exposed@*/ uentry 
01369   usymtab_getTypeEntrySafe (usymId uid)
01370   /*@globals globtab@*/
01371 {
01372   if (uid < 0 || uid >= globtab->nentries)
01373     {
01374       return uentry_undefined;
01375     }
01376 
01377       return (globtab->entries[uid]);
01378 }
01379 
01380 bool
01381   usymtab_isBoolType (usymId uid)
01382   /*@globals globtab@*/
01383 {
01384   llassert (uid >= 0 && uid < globtab->nentries);
01385 
01386   return (cstring_equal (uentry_rawName (globtab->entries[uid]),
01387                          context_getBoolName ()));
01388 }
01389  
01390 cstring
01391 usymtab_getTypeEntryName (usymId uid)
01392    /*@globals globtab@*/
01393 {
01394   uentry ue;
01395 
01396   if (dbgfree)
01397     {
01398       return (cstring_makeLiteral ("<freetype>"));
01399     }
01400 
01401   ue = usymtab_getTypeEntry (uid);
01402 
01403   if (dbgload && !uentry_isValid (ue))
01404     {
01405       return (message ("<missing type: %d>", uid));
01406     }
01407 
01408   llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
01409 
01410   return (uentry_getName (ue));
01411 }
01412 
01413 static void
01414 usymtab_rehash (/*@notnull@*/ usymtab s)
01415 {
01416   int i;
01417   
01418   if (s->htable != NULL)
01419     {
01420       hashTable_free (s->htable);
01421     }
01422   
01423   s->htable = hashTable_create (LLHASHSIZE);
01424 
01425   for (i = 0; i < s->nentries; i++)
01426     {
01427       hashTable_insert (s->htable, uentry_rawName (s->entries[i]), i);
01428     }
01429 }
01430 
01431 /*
01432 ** superficial copy of usymtab
01433 **
01434 ** DO copy spec entries 
01435 */
01436 
01437 static /*@only@*/ /*@notnull@*/ usymtab
01438 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
01439 {
01440   usymtab copytab = usymtab_createRoot ();
01441   int i;
01442 
01443   for (i = 0; i < s->nentries; i++)
01444     {
01445       usymtab_addEntryBase (copytab, s->entries[i]);
01446     }
01447 
01448   return copytab;
01449 }
01450 
01451 static void
01452 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
01453 {
01454   aliasTable_free (s->aliases);
01455   refTable_free (s->reftable, s->nentries);
01456   sfree (s->entries);
01457   /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
01458 }
01459 
01460 /*
01461 ** converts usymId from old table to sorted one
01462 */
01463 
01464 usymId 
01465   usymtab_convertId (usymId uid)
01466   /*@globals oldtab, utab@*/
01467 {
01468   uentry ue;
01469   usymId ret;
01470   cstring name;
01471 
01472   llassert (usymtab_isDefined (oldtab));
01473 
01474   ue = usymtab_getEntryAux (oldtab, uid);
01475 
01476   llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
01477 
01478   name = uentry_rawName (ue);
01479 
01480   ret = usymtab_getIndex (utab, name);
01481 
01482   llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
01483 
01484   return (ret);
01485 }
01486 
01487 void
01488 usymtab_prepareDump (void)
01489    /*@globals oldtab, utab@*/
01490    /*@modifies oldtab, utab@*/
01491 {
01492   llassert (usymtab_inGlobalScope ());
01493 
01494   llassert (oldtab == usymtab_undefined);
01495 
01496   oldtab = usymtab_shallowCopy (utab);
01497 
01498   /* 
01499      alpha compare - make sure order is same on different platforms
01500      error messages appear in same order 
01501   */
01502 
01503   qsort (utab->entries, (size_t)utab->nentries, 
01504          sizeof (*utab->entries), (int (*)(const void *, const void *)) uentry_xcomparealpha);
01505 
01506   usymtab_rehash (utab);
01507 }
01508 
01509 void
01510   usymtab_dump (FILE *fout)
01511   /*@globals utab, oldtab@*/
01512 {
01513   int i;
01514   bool neednl = FALSE;
01515   uentry lastentry = uentry_undefined;
01516   ekind lastekind = KINVALID;
01517   int linelen = 0;
01518 
01519   /*
01520   ** must call prepareDump first
01521   */
01522 
01523   llassert (oldtab != usymtab_undefined);
01524 
01525   for (i = 0; i < utab->nentries; i++)
01526     {
01527       uentry thisentry = utab->entries[i];
01528       ekind  thisekind = uentry_getKind (thisentry);
01529 
01530       
01531       if (uentry_hasRealName (thisentry)) {
01532         if (thisekind != lastekind)
01533           {
01534             if (neednl)
01535               {
01536                 check (fputc ('\n', fout) == (int) '\n');
01537               }
01538             
01539             neednl = FALSE;
01540             lastentry = uentry_undefined;
01541             fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),  
01542                      cstring_toCharsSafe (ekind_capName (thisekind)));
01543             lastekind = thisekind;
01544             linelen = 0;
01545           }
01546         
01547         if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
01548             || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH))))
01549           {
01550             cstring cdump = uentry_dump (thisentry);
01551             
01552             lastentry = thisentry;
01553             if (neednl)
01554               {
01555                 check (fputc ('\n', fout) == (int) '\n');
01556                 linelen = 0;
01557               }
01558             
01559             linelen += cstring_length (cdump);
01560             
01561             /* no new line here! */
01562             if (cstring_length (cdump) > 0) 
01563               {
01564                 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
01565               }
01566             
01567             cstring_free (cdump);
01568             neednl = TRUE;
01569           }
01570         else
01571           {
01572             cstring cdump = uentry_rawName (thisentry);
01573                     linelen += cstring_length (cdump);
01574             fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
01575           }
01576       }
01577     }
01578 
01579   if (neednl)
01580     {
01581       check (fputc ('\n', fout) == (int) '\n');
01582     }
01583 }
01584 
01585 void usymtab_load (FILE *f)
01586   /*@globals utab, globtab@*/
01587   /*@modifies utab, *f@*/
01588 {
01589   char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
01590   char *os = s;
01591   ekind kind = KINVALID;
01592   fileloc loc = g_currentloc;
01593   char c;
01594   uentry ue;
01595 
01596   dbgload = TRUE;
01597 
01598   llassert (utab == globtab);
01599   llassert (utab->nentries == 0);
01600 
01601   while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL 
01602          && *s == ';')
01603     {
01604       ; /* ignore ;-comments */
01605     }
01606 
01607   while (s != NULL && *s != ';')
01608     {
01609       
01610       if (*s == '*')
01611         {
01612           s++;
01613           kind = ekind_fromInt (getInt (&s));
01614 
01615                   goto nextiter;
01616         }
01617 
01618       if (*s == '$')
01619         {
01620           llfatalerror
01621             (cstring_makeLiteral 
01622              ("Library is in obsolete format.  Use lclint +whichlib "
01623               "to see which library is being loaded."));
01624         }
01625 
01626       ue = uentry_undump (kind, loc, &s);
01627       DPRINTF (("Load: %s", uentry_unparseFull (ue)));
01628 
01629       if (uentry_isValid (ue))
01630         {       
01631           ue = usymtab_addEntryBase (utab, ue);
01632           /*@-branchstate@*/ 
01633         } 
01634       /*@=branchstate@*/
01635 
01636       /*
01637       ** now, any other names are the same uentry
01638       */
01639 
01640       while (*(s++) == '#')
01641         {
01642           cstring name = cstring_fromCharsO (getWord (&s));
01643           uentry nue = uentry_nameCopy (name, ue);
01644 
01645           DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
01646           usymtab_addEntryBase (utab, nue);
01647         }
01648 
01649       while ((c = *s) != '\0' && (c !='\n'))
01650         {
01651           if (c != ' ' || c != '\t') 
01652             {
01653               llbuglit ("Junk in load file");
01654             }
01655 
01656           s++;
01657         }
01658 
01659     nextiter:
01660       s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
01661     }
01662 
01663   dbgload = FALSE;
01664   sfree (os);
01665 }
01666 
01667 /*
01668 ** file scope for static variables
01669 */
01670 
01671 void
01672 usymtab_enterFile ()
01673   /*@globals utab, globtab, filetab@*/
01674   /*@modifies filetab@*/
01675 {
01676   llassert (utab == globtab);
01677 
01678   # if 0
01679   /* check globals */
01680   
01681   usymtab_entries (globtab, ue)
01682     {
01683       if (sRef_hasDerived (uentry_getSref (ue)))
01684         {
01685           fprintf (g_msgstream, "Derived Global: %s\n", uentry_unparse (ue));
01686           fprintf (g_msgstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
01687         }
01688     } end_usymtab_entries ;
01689 
01690   # endif
01691 
01692   usymtab_enterScope ();
01693   filetab = utab;
01694 }
01695 
01696 void
01697 usymtab_exitFile ()
01698    /*@globals utab, filetab@*/
01699    /*@modifies filetab, utab@*/
01700 {
01701   
01702   llassert (utab->lexlevel == 1);
01703 
01704   usymtab_exitScope (exprNode_undefined);
01705   filetab = NULL;
01706 }
01707 
01708 void
01709 usymtab_enterScope ()
01710   /*@globals utab, globtab, filetab@*/
01711   /*@modifies utab@*/
01712 {
01713   usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
01714           
01715   /* unconditional scope: optimize to avoid copy */
01716   t->aliases = aliasTable_copy (utab->aliases); 
01717   utab = t;
01718   
01719   llassert (usymtab_isDefined (t->env));
01720   
01721   if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
01722     {
01723       noshadowerror = TRUE;
01724       usymtab_handleParams ();
01725       noshadowerror = FALSE;
01726     }
01727 }
01728 
01729 /*
01730 ** setup external references:
01731 **    o only, unique params alias external args
01732 **    o other params may alias anything of their type
01733 */
01734  
01735 static void
01736 usymtab_handleParams (void)
01737   /*@globals utab, globtab, filetab@*/
01738   /*@modifies utab, globtab@*/
01739 {
01740   usymtab ptab = utab->env;
01741   uentry fcn = context_getHeader ();
01742 
01743   
01744   usymtab_entries (ptab, param)
01745     {
01746       uentry ue;
01747 
01748       if (!uentry_isYield (param))
01749         {
01750           sRef uref;
01751           sRef pref = uentry_getSref (param);
01752           
01753           llassertprint (uentry_isAnyParam (param), 
01754                          ("not param: %s", 
01755                           uentry_unparseFull (param)));
01756           
01757           
01758           ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
01759                                     uentry_getType (param),
01760                                     fileloc_copy (uentry_whereDeclared (param)),
01761                                     FALSE);
01762 
01763           uentry_copyState (ue, param);
01764           uentry_setRefParam (ue);
01765           
01766           ue = usymtab_supEntrySrefReturn (ue);
01767                   
01768           /* must be after supercede! */
01769           
01770           if (!sRef_stateKnown (pref))
01771             {
01772               uentry_setDefState (ue, SS_DEFINED);
01773               uentry_setDefState (param, SS_DEFINED);
01774             }
01775           else
01776             {
01777               if (sRef_isStateSpecial (pref))
01778                 {
01779                   uentry_setDefState (ue, SS_ALLOCATED);
01780                 }
01781               else
01782                 {
01783                   uentry_setDefState (ue, sRef_getDefState (pref));
01784                 }
01785             }
01786 
01787           uref = uentry_getSref (ue);
01788           
01789           if (sRef_isStack (uref))
01790             {
01791               alkind pkind = sRef_getAliasKind (pref);
01792 
01793               if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
01794                   && !alkind_isStack (pkind))
01795                 {
01796                   sRef_setAliasKind (uref, pkind, fileloc_undefined);
01797                   sRef_setOrigAliasKind (uref, pkind);
01798                 }
01799               else
01800                 {
01801                   sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
01802                   sRef_setOrigAliasKind (uref, AK_IMPTEMP);
01803 
01804                   if (uentry_isOut (param))
01805                     {
01806                       ;
01807                     }
01808                   else
01809                     {
01810                       sRef_setDefined (uref, fileloc_undefined);
01811                     }
01812                 }
01813 
01814                     }
01815 
01816                   usymtab_addMustAlias (uref, pref);   
01817 
01818           if (!(uentry_isOnly (param) || uentry_isUnique (param)))
01819             {
01820               sRef s = sRef_makeExternal (uref);
01821 
01822                       usymtab_addMustAlias (uref, s);   
01823             }
01824           
01825           if (sRef_isKillRef (pref))
01826             {
01827               sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
01828               sRef_setOrigAliasKind (uref, AK_KILLREF);
01829             }
01830           else if (sRef_isRefCounted (uref))
01831             {
01832               sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
01833             }
01834           else
01835             {
01836               /* was AK_UNIQUE */
01837               sRef_setOrigAliasKind (uref, AK_LOCAL);
01838             }
01839         }
01840       else
01841         {
01842                 }
01843     } end_usymtab_entries;
01844 
01845 
01846   if (uentry_hasSpecialClauses (fcn))
01847     {
01848       specialClauses clauses = uentry_getSpecialClauses (fcn);
01849 
01850       specialClauses_preElements (clauses, cl)
01851         {
01852           sRefSet refs = specialClause_getRefs (cl);
01853           sRefMod modf = specialClause_getEntryFunction (cl);
01854 
01855           
01856           sRefSet_elements (refs, el)
01857             {
01858               sRef base = sRef_getRootBase (el);
01859               
01860               if (sRef_isResult (base))
01861                 {
01862                   ; /* nothing to do before */
01863                 }
01864               else if (sRef_isParam (base))
01865                 {
01866                   if (modf != NULL)
01867                     {
01868                       sRef sb = sRef_updateSref (el);
01869                       sRefSet aliases = usymtab_allAliases (sb);
01870                       
01871                                       modf (sb, fileloc_undefined);
01872                                       
01873                       sRefSet_elements (aliases, sr)
01874                         {
01875                                                   modf (sr, fileloc_undefined);
01876                                                 } end_sRefSet_elements ;
01877 
01878                       sRefSet_free (aliases);
01879                     }
01880                 }
01881               else
01882                 {
01883                   if (sRef_isValid (base))
01884                     {
01885                       BADBRANCH;
01886                     }
01887                 }
01888             } end_sRefSet_elements ;      
01889         } end_specialClauses_preElements ;
01890     }
01891   }
01892   
01893 void
01894 usymtab_enterFunctionScope (uentry fcn)
01895   /*@globals utab, filetab, globtab@*/
01896   /*@modifies utab@*/
01897 {
01898   usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
01899 
01900   if (utab->lexlevel != fileScope)
01901     {
01902       if (utab->lexlevel > fileScope)
01903         {
01904           llparseerror (cstring_makeLiteral ("New function scope inside function."));
01905           
01906           while (utab->lexlevel > fileScope)
01907             {
01908               /*@i@*/ utab = usymtab_dropEnv (utab);
01909               /*@-branchstate@*/
01910             }
01911           /*@=branchstate@*/
01912         }
01913       else
01914         {
01915           llfatalbug (cstring_makeLiteral ("New function not inside file."));
01916         }
01917     /*@-branchstate@*/ } /*@=branchstate@*/
01918 
01919   globSet_allElements (uentry_getGlobs (fcn), el)
01920     {
01921       
01922       if (sRef_isUndefGlob (el))
01923         {
01924           int index = sRef_getScopeIndex (el);
01925           sRef sr = sRef_updateSref (el);
01926           fileloc loc = uentry_whereEarliest (fcn);
01927           
01928           if (sRef_isFileStatic (el))
01929             {
01930               ctype ct = sRef_getType (el);
01931               uentry ue;
01932               
01933               llassert (usymtab_isDefined (filetab));
01934 
01935               ue = usymtab_fetchIndex (filetab, index);
01936               
01937               if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
01938                 {
01939                   sRef_setAllocated (sr, loc);
01940                 }
01941               else
01942                 {
01943                   sRef_setUndefined (sr, loc);
01944                 }
01945             }
01946           else
01947             {
01948               uentry ue = globtab->entries[index];
01949               ctype ct = uentry_getType (ue);
01950               
01951               if (ctype_isArray (ct) || ctype_isSU (ct))
01952                 {
01953                   sRef_setAllocated (sr, loc);
01954                 }
01955               else
01956                 {
01957                   sRef_setUndefined (sr, loc);
01958                 }
01959             }
01960         }
01961       else if (sRef_isAllocated (el))
01962         {
01963           sRef sr = sRef_updateSref (el);
01964           fileloc loc = uentry_whereEarliest (fcn);
01965           
01966           sRef_setAllocated (sr, loc);
01967         }
01968       else if (sRef_isPartial (el))
01969         {
01970           sRef sr = sRef_updateSref (el);
01971           fileloc loc = uentry_whereEarliest (fcn);
01972 
01973           sRef_setPartial (sr, loc);
01974         }
01975       else
01976         {
01977           /* defined */ ;
01978         }
01979     } end_globSet_allElements;
01980 
01981   utab = t;
01982 }
01983 
01984 static void
01985 usymtab_caseBranch (void)
01986   /*@modifies utab@*/
01987 {
01988   usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
01989   utab = t;
01990 }
01991 
01992 void
01993 usymtab_switchBranch (/*@unused@*/ exprNode s)
01994   /*@modifies utab@*/
01995 {
01996   usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
01997 
01998   t->aliases = aliasTable_copy (utab->aliases);
01999     utab = t;
02000 }
02001 
02002 void
02003 usymtab_trueBranch (/*@only@*/ guardSet guards)
02004   /*@modifies utab@*/
02005 {
02006   usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
02007 
02008   /*
02009   ** not true! (could be in a macro)
02010   **
02011   ** llassertprint (utab->lexlevel > paramsScope,
02012   ** ("not in scope: %s", usymtab_unparseLocal ()));
02013   **
02014   */
02015 
02016   guardSet_free (t->guards);
02017   t->guards = guards;
02018 
02019     aliasTable_free (t->aliases);
02020   t->aliases = aliasTable_copy (utab->aliases);
02021   
02022     utab = t;
02023 }
02024 
02025 /*
02026 ** consider,
02027 ** 
02028 **   { int a; if (...) a = 3; < a may be undefined here!
02029 **
02030 */
02031 
02032 void
02033 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl)
02034 {
02035   /*
02036   ** add a false branch
02037   ** (could be done more efficiently as a special case, but
02038   ** it is better to only maintain one version of the code)
02039   */
02040 
02041   usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
02042   usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
02043 }
02044 
02045 void
02046 usymtab_popCaseBranch () /*@modifies utab@*/
02047 {
02048   llassert (utab->kind == US_CBRANCH);
02049   usymtab_quietPlainExitScope ();
02050 }
02051 
02052 void
02053 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
02054 {
02055   /*
02056   ** add a false branch that must return --- that is,
02057   ** the true branch is always executed!
02058   */
02059   
02060   usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
02061   usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
02062 }
02063 
02064 void
02065 usymtab_popOrBranch (exprNode pred, exprNode expr)
02066   /*@modifies utab@*/
02067 {
02068   bool mustReturn;
02069   usymtab env = utab->env;
02070   usymtab otab = utab;
02071   int i = 0;
02072 
02073   llassert (env != NULL);
02074 
02075   if (exprNode_isError (expr))
02076     {
02077       mustReturn = FALSE;
02078     }
02079   else
02080     {
02081       mustReturn = exprNode_mustEscape (expr);
02082     }
02083 
02084   
02085   llassert (utab->kind == US_TBRANCH);
02086 
02087   /*
02088   ** merge each entry in table with its original
02089   ** unless execution cannot continue after this branch
02090   */
02091 
02092   for (i = 0; i < utab->nentries; i++)
02093     {
02094       uentry current = utab->entries[i];
02095       uentry old = usymtab_lookupAux (env, uentry_rawName (current));
02096 
02097       uentry_mergeState (old, current, exprNode_loc (expr), 
02098                          mustReturn, FALSE, TRUE, ORCLAUSE);
02099     }
02100   
02101   
02102   if (mustReturn)
02103     {
02104       env->guards = guardSet_levelUnionFree (env->guards, 
02105                                              guardSet_invert (exprNode_getGuards (pred)), 
02106                                              env->lexlevel);
02107     }
02108   else
02109     {
02110       env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
02111     }
02112  
02113   /* env is now utab */
02114   usymtab_quietPlainExitScope ();
02115 }
02116 
02117 /*
02118 ** case syntax in C is very unrestricted.  This is unfortunate.
02119 **
02120 ** A switch case is ended either by a new case or default, or
02121 ** a close } that may close the switch or some other control
02122 ** structure.  
02123 */
02124 
02125 bool
02126 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
02127   /*@modifies utab@*/
02128 {
02129   bool mustBreak = usymtab_mustBreak (utab);
02130   bool mustReturn = usymtab_mustEscape (utab);
02131   usymtab stab = utab;
02132 
02133   /*
02134   ** Find last case (or outer switch)
02135   */
02136 
02137   while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
02138     {
02139       stab = stab->env;
02140       llassert (stab != GLOBAL_ENV);
02141     }
02142 
02143   /* ??? */
02144 
02145   while (stab->kind == US_CBRANCH)
02146     {
02147       stab = stab->env;
02148       llassert (stab != GLOBAL_ENV);
02149     }
02150   
02151   /*
02152   ** if its a fall through case, merge in outside entries and last case.
02153   **
02154   ** e.g.,
02155   **        ...
02156   **        switch
02157   **          case 1: x = 3; <fall through>
02158   **          case 2: << x may not be defined
02159   **
02160   */
02161 
02162   if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
02163     {
02164       llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
02165 
02166       usymtab_entries (utab, ue)  /* but, keep track of used variables */
02167         {
02168           uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
02169 
02170           llassert (uentry_isValid (old));
02171 
02172           /* modifies ue, not old */
02173           
02174           uentry_mergeState (ue, old, exprNode_loc (last),
02175                              FALSE, FALSE, TRUE, CASECLAUSE); 
02176         } end_usymtab_entries;
02177 
02178       utab->aliases = aliasTable_levelUnion (utab->aliases, 
02179                                              stab->aliases, utab->lexlevel);
02180       
02181       /* 
02182       ** No need for a new branch.
02183       */
02184       
02185       return FALSE;
02186     }
02187   else
02188     {
02189       usymtab_caseBranch ();
02190       /*@-mustfree@*/ /*< utab->aliases >*/
02191       utab->aliases = aliasTable_copy (stab->aliases);
02192       /*@=mustfree@*/
02193       
02194       return TRUE;
02195     }
02196 }
02197 
02198 /*
02199 ** for && (both pred and expr are executed)
02200 */
02201 
02202 void
02203 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
02204   /*@modifies utab@*/
02205 {
02206   usymtab env = utab->env;
02207   usymtab otab= utab;
02208   int i = 0;
02209 
02210     llassert (utab->kind == US_TBRANCH);
02211 
02212   /*
02213   ** merge each entry in table with its original
02214   ** unless execution cannot continue after this branch
02215   */
02216 
02217   for (i = 0; i < utab->nentries; i++)
02218     {
02219       uentry current = utab->entries[i];
02220       sRef   tref = uentry_getSref (current);
02221       uentry old = usymtab_lookupAux (env, uentry_rawName (current));
02222       sRef   oref = uentry_getSref (old);
02223 
02224       /* note that is current is in a nested branch,
02225          it may create a "new" old entry. */
02226 
02227       llassert (uentry_isValid (old));
02228       uentry_mergeState (old, current, exprNode_loc (expr), 
02229                          FALSE, FALSE, TRUE, ANDCLAUSE);
02230 
02231       /*
02232       ** if is it defined by the second clause, then it should be defined.
02233       */
02234 
02235       if (sRef_isAnyDefined (tref)
02236           && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
02237         {
02238           sRef_setDefined (oref, g_currentloc);
02239         }
02240     }
02241 
02242   utab->guards = guardSet_levelUnionFree (utab->guards, 
02243                                           guardSet_invert (exprNode_getGuards (pred)), 
02244                                           utab->lexlevel);
02245   utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
02246 
02247   usymtab_quietPlainExitScope ();
02248 
02249   }
02250 
02251 /*
02252 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
02253 ** Only branches which do not return (except possibly the last branch) are included.
02254 **
02255 ** Conditionally merge state from all CBRANCHes.
02256 **
02257 ** If allpaths is TRUE, then all possible executions go through some switch 
02258 ** case, and the original scope is not merged.
02259 */
02260 
02261 void
02262 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
02263   /*@modifies utab@*/
02264 {
02265   usymtab ttab = utab;
02266   usymtab stab = ttab;
02267   usymtab ltab = ttab;
02268   bool lastMustReturn = usymtab_mustEscape (utab);
02269   int i;
02270   
02271     
02272   while (stab->kind == US_CBRANCH)
02273     {
02274       stab = stab->env;
02275       llassert (stab != GLOBAL_ENV);
02276     }
02277 
02278   while (stab->kind == US_NORMAL)
02279     {
02280       stab = stab->env;
02281       llassert (stab != GLOBAL_ENV);
02282     }
02283 
02284   llassert (stab->kind == US_SWITCH);
02285 
02286   /* go to the scope outside the switch (US_SWITCH is just a marker! */
02287   stab = stab->env; 
02288   llassert (stab != GLOBAL_ENV);
02289 
02290   
02291   ttab = ttab->env;
02292   llassert (usymtab_isDefined (ttab));
02293   
02294   if (ttab->kind == US_CBRANCH)
02295     {
02296       /* was quietPlainExitScope --- but, can't free it yet! */
02297       utab = utab->env;
02298       llassert (utab != GLOBAL_ENV);
02299 
02300       while (ttab->kind == US_CBRANCH)
02301         {
02302           /*
02303           ** (from popTrueBranch)
02304           */      
02305           
02306           bool mustReturn = usymtab_mustEscape (ttab);
02307           bool mustBreak = usymtab_mustBreak (ttab);
02308           
02309           usymtab_entries (ttab, current)
02310             {
02311               uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
02312                            /*@=compmempass@*/ 
02313               
02314               /*
02315               ** note that is this is in a nested branch,
02316               ** it may create a "new" old entry. 
02317               */
02318            
02319               if (uentry_isValid (old))
02320                 {
02321                   if (lastMustReturn)
02322                     {
02323                       uentry_mergeUses (current, old);
02324                       uentry_setState (old, current);
02325                     }
02326                   else
02327                     {
02328                       uentry_mergeState (old, current, exprNode_loc (sw),
02329                                          mustReturn, FALSE, TRUE, SWITCHCLAUSE);
02330                     }
02331                 }
02332               else
02333                 {
02334                   ;
02335                 }
02336             } end_usymtab_entries;
02337           
02338           /*
02339           ** if entry is not in symbol table for this case, merge with pre-switch
02340           ** table
02341           */
02342           
02343           if (!mustReturn && !mustBreak)
02344             {
02345               usymtab_entries (stab, current)
02346                 {
02347                   if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
02348                     {
02349                       uentry old = /*@-compmempass@*/
02350                         usymtab_lookupAux (ltab, uentry_rawName (current));
02351                       /*@=compmempass@*/
02352 
02353                       llassert (uentry_isValid (old));
02354                       uentry_mergeState (old, current, exprNode_loc (sw),
02355                                          FALSE, FALSE, TRUE, SWITCHCLAUSE);
02356                     }
02357                 } end_usymtab_entries;
02358             }
02359           
02360           ltab->env = ttab->env; 
02361           ttab = ltab->env;
02362 
02363           /*
02364           ** Suprious error, becuase of environments.
02365           */
02366 
02367           /*@i1@*/ utab = ltab;
02368 
02369           lastMustReturn = FALSE;
02370           /*@-branchstate@*/ 
02371         }
02372     }
02373   /*@=branchstate@*/
02374 
02375   /*
02376   ** now, there is one US_CBRANCH.  Merge this with the stab.
02377   */
02378   
02379     
02380   for (i = 0; i < ltab->nentries; i++)
02381     {
02382       uentry current = ltab->entries[i];
02383       uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
02384       
02385       /* note that is this is in a nested branch,
02386          it may create a "new" old entry. */
02387       
02388          
02389       if (uentry_isValid (old))
02390         {
02391           if (allpaths)
02392             {
02393               uentry_mergeUses (current, old);
02394               uentry_setState (old, current);
02395             }
02396           else
02397             {
02398               uentry_mergeState (old, current, exprNode_loc (sw), 
02399                                  FALSE, FALSE, TRUE, SWITCHCLAUSE);
02400             }
02401         }
02402       else
02403         {
02404                 }
02405     }
02406   
02407   /*
02408   ** exit the switch
02409   */
02410   
02411   
02412   /*
02413   ** switch may or may not be followed by a new scope
02414   */
02415 
02416   if (utab->kind == US_SWITCH)
02417     {
02418       usymtab_quietPlainExitScope ();  
02419     }
02420   else
02421     {
02422       usymtab_quietPlainExitScope ();
02423       llassert (utab->kind == US_SWITCH);
02424       usymtab_quietPlainExitScope ();   
02425     }
02426 
02427   }
02428 
02429 static void 
02430 updateNullState (sRef el, /*@notnull@*/ usymtab ttab, 
02431                  /*@notnull@*/ usymtab ftab, bool trueGuard)
02432 {
02433   sRef base = sRef_getRootBase (el);
02434   int level = sRef_lexLevel (base);
02435   
02436         
02437     
02438   if (sRef_isCvar (base))
02439     {
02440       usymId index = sRef_getScopeIndex (base);
02441       uentry ue = usymtab_getRefTab (ttab, level, index);
02442 
02443       if (!uentry_isLset (ue)) 
02444         {
02445           sRef sr = uentry_getSref (ue);
02446 
02447           if (trueGuard)
02448             {
02449               sRef_setDerivNullState (sr, el, NS_NOTNULL);
02450             }
02451           else 
02452             {
02453               if (!guardSet_isGuarded (ttab->guards, el) 
02454                   && !sRef_isNotNull (sr))
02455                 {
02456                   sRef_setDerivNullState (sr, el, NS_DEFNULL);
02457                                 }
02458             }
02459         }
02460       else
02461         {
02462                 }
02463       
02464       ue = usymtab_getRefTab (ftab, level, index);
02465       
02466       if (!uentry_isLset (ue)) 
02467         {
02468           sRef sr = uentry_getSref (ue);
02469           
02470           
02471           if (!trueGuard) /* yikes!  forgot the ! */
02472             {
02473               sRef_setDerivNullState (sr, el, NS_NOTNULL);
02474             }
02475           else 
02476             {
02477               
02478               if (!guardSet_isGuarded (ftab->guards, el)
02479                   && !sRef_isNotNull (sr))
02480                 {
02481                   sRef_setDerivNullState (sr, el, NS_DEFNULL);
02482                                 }
02483             }
02484         }
02485       else
02486         {
02487                 }
02488       
02489           }
02490 
02491       }
02492 
02493 void
02494 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch, 
02495                      bool isOpt, clause cl)
02496      /*@modifies utab@*/
02497 {
02498   int i = 0;
02499   usymtab ftab = utab;
02500   usymtab ttab = utab->env;
02501 
02502   fileloc loc;
02503   usymtab env;
02504   guardSet guards = exprNode_getGuards (pred);
02505   sRefSet tguards = guardSet_getTrueGuards (guards);
02506   sRefSet fguards = guardSet_getFalseGuards (guards);
02507   bool mustReturnT = exprNode_mustEscape (tbranch);
02508   bool mustReturnF = exprNode_mustEscape (fbranch);
02509   
02510   if (exprNode_isDefined (fbranch))
02511     {
02512       loc = exprNode_loc (fbranch);
02513     }
02514   else
02515     {
02516       loc = exprNode_loc (tbranch);
02517     }
02518 
02519   llassert (usymtab_isDefined (ttab));
02520   
02521   env = ttab->env;
02522   
02523   llassert (usymtab_isDefined (env));
02524   llassert (ftab->kind == US_FBRANCH);
02525   llassert (ttab->kind == US_TBRANCH);
02526 
02527   /*
02528   ** For each element that is true guarded (i.e., if (x != NULL)) 
02529   **          make x = null in false branch,
02530   **          and x = notnull in true branch.
02531   **          unless x was set locally in that branch.
02532   ** For each element that is false guarded (x == NULL) 
02533   **          make x = null in true, notnull in false.
02534   **                      
02535   ** For each element that is either guarded (pred(x)) 
02536   **     
02537   */
02538   
02539   sRefSet_allElements (tguards, el)
02540     {
02541       updateNullState (el, ttab, ftab, TRUE);
02542     } end_sRefSet_allElements;
02543     
02544   sRefSet_allElements (fguards, el)
02545     {
02546       updateNullState (el, ttab, ftab, FALSE);
02547     } end_sRefSet_allElements;
02548 
02549   /*
02550   ** 
02551   ** if an entry is in both true and false, merge the entries,
02552   ** then replace original with new state.
02553   **
02554   ** if an entry is in one table, merge it with the original.
02555   */
02556     
02557   for (i = 0; i < ftab->nentries; i++)
02558     {
02559       uentry fthis = ftab->entries[i];
02560       uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
02561       int    tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
02562       
02563       if (uentry_isUndefined (old))
02564         {
02565           /* possible entry was added as an undefined id */
02566           continue;
02567         }
02568       
02569       if (tindex != NOT_FOUND)
02570         {
02571           uentry tthis = ttab->entries[tindex];
02572           
02573           /* note that is this is in a nested branch,
02574              it may create a "new" old entry. */
02575           
02576           if (!mustReturnF)
02577             {
02578               if (!mustReturnT)
02579                 {
02580                   
02581                   uentry_mergeState (fthis, tthis, loc,
02582                                      mustReturnT, FALSE, FALSE, cl);
02583                 }
02584               else
02585                 {
02586                   uentry_mergeUses (fthis, tthis);
02587                 }
02588               
02589               uentry_setState (old, fthis);
02590               
02591               /*@-mustfree@*/ 
02592             } 
02593           /*@=mustfree@*/
02594           else
02595             {
02596               uentry_setState (old, tthis);
02597               uentry_mergeState (old, fthis, loc, mustReturnF, 
02598                                  TRUE, FALSE, cl);
02599             }
02600           
02601           ttab->entries[tindex] = uentry_undefined;
02602           uentry_free (tthis);
02603         }
02604       else
02605         {
02606           uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
02607         }
02608     }
02609 
02610   for (i = 0; i < ttab->nentries; i++)
02611     {
02612       uentry current = ttab->entries[i];
02613       
02614       if (!uentry_isUndefined (current)) 
02615         {
02616           uentry old = usymtab_lookupAux (env, uentry_rawName (current));
02617 
02618           llassertprint (!uentry_isUndefined (old), ("name: <%s>", 
02619                                                      uentry_rawName (current)));
02620           if (mustReturnF)
02621             {
02622               uentry_mergeUses (current, old); 
02623               uentry_setState (old, current);
02624             }
02625           else
02626             {
02627               /*
02628               ** assumes false branch is a fall-through if
02629               ** fbranch is not defined.  This is true, unless
02630               ** where was some greivous error in processing
02631               ** the else branch of an if-then, in which case
02632               ** this is probably the right thing to do anyway.
02633               */
02634 
02635               uentry_mergeState (old, current, loc, mustReturnT, 
02636                                  FALSE, isOpt, cl);
02637             }
02638         }
02639     }
02640 
02641   
02642   /*
02643   ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
02644   ** if they are present.
02645   */
02646 
02647   llassert (NOALIAS (env->aliases, ttab->aliases));
02648   llassert (NOALIAS (env->aliases, ftab->aliases));
02649 
02650   aliasTable_free (env->aliases);  
02651 
02652   env->aliases = aliasTable_levelUnionNew (ttab->aliases, 
02653                                            ftab->aliases, env->lexlevel);
02654 
02655   aliasTable_fixSrefs (env->aliases);
02656   
02657   /* exit true and false scopes */
02658   usymtab_quietPlainExitScope ();
02659   usymtab_quietPlainExitScope ();
02660   
02661   if (mustReturnT)
02662     {
02663       utab->guards = guardSet_levelUnionFree 
02664         (utab->guards, 
02665          guardSet_invert (exprNode_getGuards (pred)), 
02666          utab->lexlevel);
02667     }
02668 
02669   if (mustReturnF)
02670     {
02671       utab->guards = guardSet_levelUnion (utab->guards, 
02672                                           exprNode_getGuards (pred), 
02673                                           utab->lexlevel);
02674     }
02675 
02676   DPRINTF (("Here."));
02677 }
02678 
02679 static void usymtab_fixCases (void) /*@modifies utab@*/ {
02680   while (utab->kind == US_CBRANCH)
02681     {
02682       usymtab_quietPlainExitScope ();
02683     }
02684 
02685   llassert (utab->kind != US_CBRANCH);
02686 }
02687 
02688 void
02689 usymtab_altBranch (/*@only@*/ guardSet guards)
02690   /*@modifies utab@*/
02691 {
02692   usymtab t = usymtab_create (US_FBRANCH, utab, FALSE);
02693   usymtab parent = utab->env;
02694 
02695   /*
02696   ** If we are in a case, need to close it.  The C syntax
02697   ** is very liberal, so this kludge is necessary.
02698   */
02699 
02700   usymtab_fixCases ();
02701 
02702   DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
02703   llassert (utab->kind == US_TBRANCH);
02704   llassert (parent != GLOBAL_ENV);
02705 
02706   guardSet_free (t->guards);
02707   t->guards = guards;
02708 
02709   aliasTable_free (t->aliases);
02710   t->aliases = aliasTable_copy (parent->aliases);
02711     
02712   utab = t;
02713 }
02714 
02715 void
02716 usymtab_allDefined (void)
02717    /*@globals utab, globtab@*/
02718 {
02719   int i;
02720 
02721   llassert (utab == globtab);
02722 
02723   for (i = 0; i < utab->nentries; i++)
02724     {
02725       uentry e = utab->entries[i];
02726 
02727       if (uentry_isPriv (e))
02728         {
02729          ; /* no need to define it */
02730         }
02731       else
02732         {
02733           if (context_getFlag (FLG_SPECUNDECL))
02734             {
02735               fileloc sloc = uentry_whereSpecified (e);
02736               fileloc dloc = uentry_whereDeclared (e);
02737 
02738               if (fileloc_isDefined (sloc) 
02739                   && !uentry_isFakeTag (e)
02740                   && !fileloc_isDefined (dloc))
02741                 {
02742                   voptgenerror 
02743                     (FLG_SPECUNDECL,
02744                      message ("%s %q specified but not declared",
02745                               ekind_capName (uentry_getKind (e)),
02746                               uentry_getName (e)),
02747                      sloc);
02748                 }
02749             }
02750           
02751           if (!uentry_isCodeDefined (e))
02752             {
02753               fileloc dloc = uentry_whereDeclared (e);
02754               
02755               if (fileloc_isLib (dloc))
02756                 {
02757                  ;
02758                 }
02759               else if (fileloc_isDefined (dloc))
02760                 {
02761                   if (!uentry_isAnyTag (e))
02762                     {
02763                       if (fileloc_isUser (dloc))
02764                         {
02765                           voptgenerror 
02766                             (FLG_DECLUNDEF,
02767                              message ("%s %q declared but not defined",
02768                                       ekind_capName (uentry_getKind (e)),
02769                                       uentry_getName (e)),
02770                              dloc);
02771                         }
02772                     }
02773                 }
02774               else
02775                 {
02776                   fileloc sloc = uentry_whereSpecified (e);
02777 
02778                   if (fileloc_isDefined (sloc) 
02779                       && !fileloc_isImport (sloc)
02780                       && !fileloc_isLib (sloc)
02781                       && !fileloc_isPreproc (sloc)
02782                       && !uentry_isFakeTag (e))
02783                     {
02784                       if (uentry_isVariable (e) || uentry_isFunction (e))
02785                         {
02786                           voptgenerror 
02787                             (FLG_SPECUNDEF,
02788                              message ("%s %q specified but not declared or defined",
02789                                       ekind_capName (uentry_getKind (e)),
02790                                       uentry_getName (e)),
02791                              sloc);
02792                         }
02793                       else
02794                         {
02795                           voptgenerror 
02796                             (FLG_SPECUNDEF,
02797                              message ("%s %q specified but not defined",
02798                                       ekind_capName (uentry_getKind (e)),
02799                                       uentry_getName (e)),
02800                              sloc);
02801                         }
02802                     }
02803                 }
02804             }
02805         }
02806     }
02807 }
02808 
02809 void usymtab_exportHeader (void)
02810      /*@globals utab@*/
02811 {
02812   int i;
02813 
02814   for (i = 0; i < utab->nentries; i++)
02815     {
02816       uentry ce = utab->entries[i];
02817 
02818       if (!uentry_isDatatype (ce) 
02819           && !uentry_isAnyTag (ce) 
02820           && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
02821           && !uentry_isExternal (ce)
02822           && !uentry_isForward (ce))
02823         {
02824           fileloc fwhere = uentry_whereDeclared (ce);
02825 
02826           if (fileloc_isUndefined (fwhere)
02827               && uentry_isFunction (ce))
02828             {
02829               fwhere = uentry_whereDefined (ce);
02830             }
02831 
02832           if (fileloc_isDefined (fwhere) 
02833               && !fileloc_isHeader (fwhere)
02834               && !(fileloc_isSpecialFile (fwhere)
02835                    && !context_getFlag (FLG_UNUSEDSPECIAL)))
02836             {
02837               if (uentry_isVariable (ce))
02838                 {
02839                   if (optgenerror
02840                       (FLG_EXPORTHEADERVAR,
02841                        message ("%s %q exported but not declared in header file", 
02842                                 ekind_capName (uentry_getKind (ce)),
02843                                 uentry_getName (ce)),
02844                        fwhere))
02845                     {
02846                       uentry_showDefSpecInfo (ce, fwhere);
02847                     }
02848                 }
02849               else
02850                 {
02851                   if (!uentry_isIter (ce)
02852                       && !uentry_isEndIter (ce)
02853                       && !uentry_isExpandedMacro (ce))
02854                     {
02855                       if (uentry_isFunction (ce) 
02856                           && cstring_equalLit (uentry_rawName (ce), "main"))
02857                         {
02858                           ; /* no error for main */
02859                         }
02860                       else
02861                         {
02862                           if (optgenerror
02863                               (FLG_EXPORTHEADER,
02864                                message ("%s %q exported but not declared "
02865                                         "in header file", 
02866                                         ekind_capName (uentry_getKind (ce)),
02867                                         uentry_getName (ce)),
02868                                fwhere))
02869                             {
02870                               uentry_showDefSpecInfo (ce, fwhere);
02871                             }
02872                         }
02873                     }
02874                 }
02875             }
02876         }
02877     }
02878 }
02879 
02880 void usymtab_exportLocal (void)
02881    /*@globals utab@*/
02882 {
02883   int i;
02884 
02885   
02886   for (i = 0; i < utab->nentries; i++)
02887     {
02888       uentry ce = utab->entries[i];
02889 
02890       
02891       if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce) 
02892           && !uentry_isEitherConstant (ce) 
02893           && !uentry_isIter (ce)
02894           && !uentry_isEndIter (ce)
02895           && !uentry_isExpandedMacro (ce)
02896           && uentry_isUsed (ce))
02897         {
02898           /* check static uses */
02899           filelocList fuses = uentry_getUses (ce);
02900           fileloc mod = uentry_whereDefined (ce);
02901           bool ok = filelocList_isEmpty (fuses);
02902           fileloc fwhere = uentry_whereDeclared (ce);
02903 
02904           if (fileloc_isSpecialFile (fwhere)
02905               && !context_getFlag (FLG_UNUSEDSPECIAL))
02906             {
02907               ok = TRUE; /* no errors for special files */
02908             }
02909           else
02910             {
02911               filelocList_elements (fuses, uloc)
02912                 {
02913                   if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
02914                     {
02915                       ok = TRUE;
02916                       /*@innerbreak@*/ break;
02917                     }
02918                 } end_filelocList_elements;
02919             }
02920 
02921           if (!ok)
02922             {
02923               if (optgenerror
02924                   (FLG_EXPORTLOCAL,
02925                    message ("%s exported but not used outside %s: %q", 
02926                             ekind_capName (uentry_getKind (ce)),
02927                             fileloc_getBase (mod),
02928                             uentry_getName (ce)),
02929                    fwhere))
02930                 {
02931                   uentry_showDefSpecInfo (ce, fwhere);
02932                 }
02933             }
02934         }
02935     }
02936 }
02937 
02938 void
02939 usymtab_allUsed (void)
02940   /*@globals utab@*/
02941 {
02942   int i;
02943   bool isFileStatic = usymtab_inFileScope ();
02944   cstring last_file = cstring_undefined;
02945 
02946   for (i = 0; i < utab->nentries; i++)
02947     {
02948       bool hasError = FALSE;
02949       uentry ce = utab->entries[i];
02950       fileloc fwhere = uentry_whereDeclared (ce);
02951 
02952       if (fileloc_isUndefined (fwhere))
02953         {
02954           fwhere = uentry_whereDefined (ce);
02955         }
02956 
02957       if (fileloc_isInvalid (fwhere) 
02958           || fileloc_isLib (fwhere) 
02959           || fileloc_isBuiltin (fwhere)
02960           || ((fileloc_isSpecialFile (fwhere)
02961                || fileloc_isSpecialFile (uentry_whereDefined (ce)))
02962               && !context_getFlag (FLG_UNUSEDSPECIAL)))
02963         {
02964           ;
02965         }
02966       else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
02967         {
02968           cstring fname = fileloc_filename (fwhere);
02969 
02970           if (cstring_isUndefined (last_file))
02971             {
02972               last_file = fname;
02973             }
02974           else if (cstring_equal (fname, last_file))
02975             {
02976             }
02977           else
02978             {
02979               cleanupMessages ();
02980               last_file = fname;
02981             } 
02982           
02983           if (uentry_isParam (ce))
02984             {
02985               if (context_inMacro ())
02986                 {
02987                   sRef cref = uentry_getSref (ce);
02988 
02989                   if (uentry_isYield (ce))
02990                     {
02991                       ; /* no checks (for now) */
02992                     }
02993                   else if (sRef_isSafe (cref))
02994                     {
02995                       ; /* no error */
02996                     }
02997                   else
02998                     {
02999                       if (uentry_hasRealName (ce))
03000                         {
03001                           hasError = 
03002                             optgenerror (FLG_MACROPARAMS,
03003                                          message ("Macro parameter %q not used", 
03004                                                   uentry_getName (ce)),
03005                                          fwhere);
03006                         }
03007                     }
03008                 }
03009               else 
03010                 {
03011                   if (cstring_equalFree (uentry_getName (ce), 
03012                                          cstring_makeLiteral ("...")))
03013                     {
03014                       ;
03015                     }
03016                   else
03017                     {
03018                       hasError = optgenerror (FLG_PARAMUNUSED,
03019                                               message ("Parameter %q not used",
03020                                                        uentry_getName (ce)),
03021                                               fwhere);
03022                     }
03023                 }
03024             } /* isParam */
03025           else if (uentry_isFunction (ce) || uentry_isIter (ce))
03026             {
03027               if (fileloc_isUser (fwhere))
03028                 {
03029                   hasError = optgenerror
03030                     (FLG_FUNCUNUSED, 
03031                      message ("%q %q declared but not used", 
03032                               cstring_makeLiteral 
03033                               (uentry_isIter (ce) ? "Iterator" 
03034                                : (isFileStatic ? "File static function" : "Function")),
03035                               uentry_getName (ce)),
03036                      fwhere);
03037                 }
03038             }
03039           else if (uentry_isEndIter (ce))
03040             {
03041               ; /* no error (already reported for iter */
03042             }
03043           else if (uentry_isEnumConstant (ce))
03044             {
03045               if (fileloc_isUser (fwhere))
03046                 {
03047                   hasError = optgenerror
03048                     (FLG_ENUMMEMUNUSED,
03049                      message ("Enum member %q not used", 
03050                               uentry_getName (ce)),
03051                      fwhere);
03052                 }
03053             }
03054           else if (uentry_isConstant (ce))
03055             {
03056               if (fileloc_isUser (fwhere))
03057                 {
03058                   hasError = optgenerror
03059                     (FLG_CONSTUNUSED,
03060                      message ("Constant %q declared but not used", 
03061                               uentry_getName (ce)),
03062                      fwhere);
03063                 }
03064             }
03065           else if (uentry_isDatatype (ce))
03066             {
03067               if (fileloc_isUser (fwhere))
03068                 {
03069                   hasError = optgenerror
03070                     (FLG_TYPEUNUSED,
03071                      message ("Type %q declared but not used", 
03072                               uentry_getName (ce)),
03073                      fwhere);
03074                 }
03075             }
03076           else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
03077             { /* errors for ref params will be reported in the next scope */
03078               llassertprint (uentry_isVar (ce), 
03079                              ("ce: %s", uentry_unparseFull (ce)));
03080 
03081               if (ctype_isFunction (uentry_getType (ce)))
03082                 {
03083                   if (fileloc_isUser (fwhere))
03084                     {
03085                       hasError = optgenerror
03086                         (FLG_FUNCUNUSED,
03087                          message ("%q %q declared but not used", 
03088                                   cstring_makeLiteral 
03089                                   (isFileStatic ? "File static function" 
03090                                    : "Function"),
03091                                   uentry_getName (ce)),
03092                          fwhere);
03093                     }
03094                 }
03095               else 
03096                 {
03097                   if (fileloc_isUser (fwhere))
03098                     {
03099                       
03100                       
03101                       hasError = optgenerror 
03102                         (FLG_VARUNUSED,
03103                          message ("%q %q declared but not used", 
03104                                   cstring_makeLiteral 
03105                                   (isFileStatic ? "File static variable" 
03106                                    : "Variable"), 
03107                                   uentry_getName (ce)),
03108                          fwhere);
03109                     }
03110                 }
03111             }
03112           else
03113             {
03114               ; /* no errors */
03115             }
03116         } /* unused */
03117       else if (uentry_isDatatype (ce) || uentry_isAnyTag (ce))
03118         { /* check all fields */
03119           ctype ct = uentry_getRealType (ce); 
03120 
03121           
03122           while (ctype_isAP (ct))
03123             {
03124               ct = ctype_getBaseType (ct);
03125             }
03126 
03127           
03128           if (ctype_isSU (ct))
03129             {
03130               uentryList fields = ctype_getFields (ct);
03131 
03132               uentryList_elements (fields, field)
03133                 {
03134                   if (!uentry_isUsed (field))
03135                     {
03136                       if (uentry_hasName (ce))
03137                         {
03138                           hasError |= optgenerror 
03139                             (FLG_FIELDUNUSED,
03140                              message ("Field %q of %s %q declared but not used", 
03141                                       uentry_getName (field),
03142                                       cstring_makeLiteralTemp
03143                                       (ctype_isStruct (ct) ? "structure" : "union"),
03144                                       uentry_getName (ce)),
03145                              uentry_whereEarliest (field));
03146                         }
03147                       else
03148                         {
03149                           hasError |= optgenerror 
03150                             (FLG_FIELDUNUSED,
03151                              message ("Field %q of unnamed %s declared but not used", 
03152                                       uentry_getName (field),
03153                                       cstring_makeLiteralTemp
03154                                       (ctype_isStruct (ct) ? "structure" : "union")),
03155                              uentry_whereEarliest (field));
03156                         }
03157                       
03158                       uentry_setUsed (field, fileloc_undefined);
03159                     }
03160                 } end_uentryList_elements;
03161             }
03162         }
03163       else
03164         {
03165           ; /* no errors */
03166         }
03167 
03168       if (hasError)
03169         {
03170           if (uentry_isParam (ce) && context_inMacro ())
03171             {
03172               if (fileloc_isDefined (uentry_whereSpecified (ce)))
03173                 {
03174                   uentry_showWhereSpecified (ce);
03175                 }
03176             }
03177           else
03178             {
03179               uentry_showDefSpecInfo (ce, fwhere);
03180             }
03181 
03182           uentry_setUsed (ce, fileloc_undefined);
03183         }
03184     }
03185 }
03186 
03187 static void
03188 checkGlobalReturn (uentry glob, sRef orig)
03189 {
03190   sRef sr = uentry_getSref (glob);
03191   
03192   
03193   if (context_getFlag (FLG_GLOBSTATE))
03194     {
03195       if (sRef_isKilledGlob (orig))
03196         {
03197           if (sRef_isStateUndefined (sr)
03198               || sRef_isUnuseable (sr)
03199               || sRef_isStateUnknown (sr)
03200               || sRef_isDead (sr))
03201             {
03202               ;
03203             }
03204           else
03205             {
03206               ctype ct = ctype_realType (uentry_getType (glob));
03207 
03208               if (ctype_isVisiblySharable (ct))
03209                 {
03210                   if (optgenerror 
03211                       (FLG_GLOBSTATE,
03212                        message 
03213                        ("Killed global %q not released before return",
03214                         uentry_getName (glob)),
03215                        g_currentloc))
03216                     {
03217                       sRef_showStateInfo (sr);
03218                                     }
03219                 }
03220               else
03221                 {
03222                                   sRef_protectDerivs ();
03223                   (void) checkGlobalDestroyed (sr, g_currentloc);
03224                   sRef_clearProtectDerivs ();
03225                 }
03226             }
03227         }
03228       else
03229         {
03230           if (sRef_isStateUndefined (sr))
03231             {
03232               if (optgenerror (FLG_GLOBSTATE,
03233                                message 
03234                                ("Function returns with global %q undefined",
03235                                 uentry_getName (glob)),
03236                                g_currentloc))
03237                 {
03238                   sRef_showStateInfo (sr);
03239                 }
03240             }
03241           else 
03242             {
03243               if (sRef_isDead (sr))
03244                 {
03245                   if (optgenerror 
03246                       (FLG_GLOBSTATE,
03247                        message ("Function returns with global %q "
03248                                 "referencing released storage",
03249                                 uentry_getName (glob)),
03250                        g_currentloc))
03251                     {
03252                       sRef_showStateInfo (sr);
03253                       sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
03254                     }
03255                 }
03256               
03257               if (ctype_isRealPointer (uentry_getType (glob)) &&
03258                   sRef_possiblyNull (sr) && !uentry_possiblyNull (glob))
03259                 {
03260                   if (optgenerror 
03261                       (FLG_GLOBSTATE,
03262                        message ("Function returns with non-null global %q "
03263                                 "referencing null storage",
03264                                 uentry_getName (glob)),
03265                        g_currentloc))
03266                     {
03267                       sRef_showNullInfo (sr);
03268                     }
03269                 }
03270               else
03271                 {
03272                   checkGlobReturn (glob);
03273                 }
03274             }
03275         }
03276     }
03277 }
03278 
03279 /*
03280 ** remember: check alias globals
03281 */
03282 
03283 void usymtab_checkFinalScope (bool isReturn)
03284   /*@globals utab@*/
03285 {
03286   bool mustFree = context_getFlag (FLG_MUSTFREE);
03287   bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
03288   /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
03289   sRefSet checked = sRefSet_new ();
03290   usymtab stab = utab;
03291   int i;
03292     
03293   /*
03294   ** need to check all scopes out to function parameters.
03295   */
03296 
03297   do 
03298     {
03299       for (i = 0; i < stab->nentries; i++)
03300         {
03301           uentry ce = stab->entries[i];
03302           sRef sr = uentry_getSref (ce);
03303           sRef rb = sRef_getRootBase (sr);
03304 
03305           if (ctype_isFunction (uentry_getType (ce)))
03306             {
03307               /*@innercontinue@*/ continue;
03308             }
03309 
03310           if (mustFree)
03311             {
03312               DPRINTF (("Check entry: %s", uentry_unparseFull (ce)));
03313 
03314               if (!sRefSet_member (checked, sr) && !sRef_isGlobal (rb))
03315                 {
03316                   if (ctype_isRealSU (uentry_getType (ce))
03317                       && !uentry_isAnyParam (ce)
03318                       && !uentry_isRefParam (ce)
03319                       && !uentry_isStatic (ce)
03320                       && !sRef_isDependent (sr)
03321                       && !sRef_isOwned (sr))
03322                     {
03323                       sRefSet als = usymtab_allAliases (sr);
03324 
03325                       
03326                       if (sRefSet_isEmpty (als))
03327                         {
03328                           checkLocalDestroyed (sr, g_currentloc);
03329                         }
03330                       else
03331                         {
03332                           /* aliased, no problem */ ;
03333                         }
03334 
03335                       sRefSet_free (als);
03336                     }
03337                   else if
03338                     (!uentry_isStatic (ce)
03339                      && ((sRef_isNewRef (sr))
03340                          || (((sRef_isOnly (sr) || sRef_isFresh (sr) 
03341                                || sRef_isKeep (sr) || sRef_isOwned (sr))
03342                               && !sRef_isDead (sr))
03343                              && (!sRef_definitelyNull (sr))
03344                              && (!usymtab_isProbableNull (sr)))))
03345                       {
03346                         bool hasError = TRUE;
03347                         
03348                         /*
03349                         ** If its a scope exit, check if there is an alias.
03350                         ** If so, make it only.  If not, there is an error.
03351                         */
03352                         
03353                         if (!isReturn)
03354                           {
03355                             if (canLoseReference (sr, g_currentloc))
03356                               {
03357                                 hasError = FALSE;
03358                               }
03359                           }
03360                         
03361                         if (hasError)
03362                           {
03363                             if (sRef_hasLastReference (sr))
03364                               {
03365                                 sRef ar = sRef_getAliasInfoRef (sr);
03366                                 
03367                                 if (optgenerror 
03368                                     (FLG_MUSTFREE,
03369                                      message
03370                                      ("Last reference %q to %s storage %qnot %q before %q",
03371                                       sRef_unparse (sr),
03372                                       alkind_unparse (sRef_getAliasKind (sr)),
03373                                       sRef_unparseOpt (ar),
03374                                       cstring_makeLiteral (sRef_isKeep (sr) 
03375                                                            ? "transferred" : "released"),
03376                                       cstring_makeLiteral (isReturn 
03377                                                            ? "return" : "scope exit")),
03378                                      g_currentloc))
03379                                   {
03380                                     sRef_showRefLost (sr);
03381                                   }
03382                               }
03383                             else if (sRef_isNewRef (sr))
03384                               {
03385                                 if (optgenerror
03386                                     (FLG_MUSTFREE,
03387                                      message 
03388                                      ("%q %q not released before %q",
03389                                       cstring_makeLiteral 
03390                                       (alkind_isKillRef (sRef_getOrigAliasKind (sr))
03391                                        ? "Kill reference parameter" : "New reference"),
03392                                       uentry_getName (ce),
03393                                       cstring_makeLiteral (isReturn
03394                                                            ? "return" : "scope exit")),
03395                                      g_currentloc))
03396                                   {
03397                                     sRef_showAliasInfo (sr);
03398                                   }
03399                               }
03400                             else 
03401                               {
03402                                 if (ctype_isRealSU (sRef_getType (sr)))
03403                                   {
03404                                                                     checkStructDestroyed (sr, g_currentloc);
03405                                   }
03406                                 else
03407                                   {
03408                                     if (optgenerror
03409                                         (FLG_MUSTFREE,
03410                                          message 
03411                                          ("%s storage %q not %q before %q",
03412                                           alkind_capName (sRef_getAliasKind (sr)),
03413                                           uentry_getName (ce),
03414                                           cstring_makeLiteral (sRef_isKeep (sr) 
03415                                                                ? "transferred" : "released"),
03416                                           cstring_makeLiteral (isReturn 
03417                                                                ? "return" : "scope exit")),
03418                                          g_currentloc))
03419                                       {
03420                                         sRef_showAliasInfo (sr);
03421                                       }
03422                                   }
03423                               }
03424                           }
03425                       }
03426                   else
03427                     {
03428                       ;
03429                     }
03430                 }
03431               else if (mustDefine && uentry_isOut (ce))
03432                 {
03433                   if (!ynm_toBoolStrict (sRef_isReadable (sr)))
03434                     {
03435                       voptgenerror 
03436                         (FLG_MUSTDEFINE,
03437                          message ("Out storage %q not defined before %q",
03438                                   uentry_getName (ce),
03439                                   cstring_makeLiteral 
03440                                   (isReturn ? "return" : "scope exit")),
03441                          g_currentloc);
03442                       
03443                       /* uentry_showWhereDeclared (ce); */
03444                     }
03445                 }
03446               else
03447                 {
03448                   ; 
03449                 }
03450               
03451               /*
03452               ** also check state is okay
03453               */
03454 
03455               if (usymtab_lexicalLevel () > functionScope
03456                   && uentry_isVariable (ce)
03457                   && (sRef_isLocalVar (sr)
03458                       && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
03459                 {
03460                   sRefSet ab = usymtab_aliasedBy (sr);
03461 
03462                   /* should do something more efficient here */
03463 
03464                   if (sRefSet_isEmpty (ab))
03465                     {
03466                       /* and no local ref */
03467                       checkLoseRef (ce);
03468                     }
03469                   else
03470                     {
03471                       ;
03472                     }
03473                   
03474                   sRefSet_free (ab);
03475                 }
03476               else 
03477                 {
03478                   ;
03479                 }
03480               
03481               checked = sRefSet_insert (checked, sr);
03482             }
03483         }
03484       llassert (usymtab_isDefined (stab->env));
03485 
03486       if (usymtab_isBranch (stab))
03487         {
03488           stab = usymtab_dropEnv (stab);
03489         }
03490       else
03491         {
03492           stab = stab->env;
03493         }
03494 
03495       llassert (stab != usymtab_undefined);
03496     } while (isReturn && (stab->lexlevel >= paramsScope));
03497 
03498     sRefSet_free (checked);
03499 
03500   /*
03501   ** for returns:
03502   **      all globals are appropriately defined
03503   **      all parameters are appropriately defined
03504   **      special clauses are followed
03505   */
03506 
03507   if (isReturn || (utab->lexlevel == paramsScope))
03508     {
03509       uentry fcn = context_getHeader ();
03510       uentryList params = context_getParams ();
03511       globSet uglobs = context_getUsedGlobs ();
03512       globSet sglobs = context_getGlobs ();
03513 
03514             
03515       if (isReturn && context_maybeSet (FLG_GLOBALIAS))
03516         { 
03517           aliasTable_checkGlobs (utab->aliases); 
03518         }
03519 
03520       /*
03521       ** special clauses (defines, sets, allocates, releases) 
03522       */
03523 
03524       if (uentry_hasSpecialClauses (fcn))
03525         {
03526           specialClauses clauses = uentry_getSpecialClauses (fcn);
03527 
03528           specialClauses_elements (clauses, cl)
03529             {
03530               if (specialClause_isAfter (cl)) 
03531                 { /* evs - 2000 07 10 - added this */
03532                   sRefTest tst = specialClause_getPostTestFunction (cl);
03533                   sRefSet rfs = specialClause_getRefs (cl);
03534                   
03535                   sRefSet_elements (rfs, el)
03536                     {
03537                       sRef base = sRef_getRootBase (el);
03538                       
03539                       if (sRef_isResult (base))
03540                         {
03541                           ; 
03542                         }
03543                       else if (sRef_isParam (base))
03544                         {
03545                           sRef sr = sRef_updateSref (base);
03546                           sr = sRef_fixBase (el, sr);
03547                           
03548                           if (tst != NULL && !tst (sr))
03549                             {
03550                               if (optgenerror 
03551                                   (specialClause_postErrorCode (cl),
03552                                    message ("%s storage %qcorresponds to "
03553                                             "storage listed in %q clause",
03554                                             specialClause_postErrorString (cl, sr),
03555                                             sRef_unparseOpt (sr),
03556                                             specialClause_unparseKind (cl)),
03557                                    g_currentloc))
03558                                 {
03559                                   sRefShower ss = specialClause_getPostTestShower (cl);
03560                                   
03561                                   if (ss != NULL)
03562                                     {
03563                                       ss (sr);
03564                                     }
03565                                 }  
03566                             }
03567                         }
03568                       else
03569                         {
03570                           if (sRef_isMeaningful (el))
03571                             {
03572                               BADBRANCH;
03573                             }
03574                         }
03575                     } end_sRefSet_elements ;
03576                 }
03577             } end_specialClauses_elements ;
03578         }
03579       
03580       /*
03581       ** check parameters on return
03582       */
03583 
03584       uentryList_elements (params, arg)
03585         {
03586           if (!uentry_isElipsisMarker (arg))
03587             {
03588               ctype rt = ctype_realType (uentry_getType (arg));
03589 
03590               if (ctype_isMutable (rt) || ctype_isSU (rt))
03591                 {
03592                   uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
03593                   checkParamReturn (param);
03594                 }
03595             }
03596         } end_uentryList_elements;
03597       
03598       globSet_allElements (sglobs, el)
03599         {
03600           uentry current = sRef_getUentry (el);
03601 
03602           if (uentry_isVariable (current) && !uentry_isRealFunction (current))
03603             {
03604               checkGlobalReturn (current, el);
03605             }
03606         } end_globSet_allElements;
03607 
03608       globSet_allElements (uglobs, el)
03609         {
03610           if (!globSet_member (sglobs, el))
03611             {
03612               uentry current = sRef_getUentry (el);
03613               
03614                       
03615               if (uentry_isVariable (current)
03616                   && !uentry_isRealFunction (current))
03617                 {
03618                   checkGlobalReturn (current, sRef_undefined);
03619                 }
03620             }
03621         } end_globSet_allElements;
03622     }
03623   
03624   }
03625 
03626 void
03627 usymtab_quietExitScope (fileloc loc) 
03628    /*@globals utab, globtab, filetab; @*/ 
03629    /*@modifies utab@*/
03630 {
03631   usymtab t = utab->env;
03632 
03633   if (utab->reftable != NULL)
03634     {
03635       int i;
03636 
03637       for (i = 0; i < utab->nentries; i++)
03638         {
03639           uentry current = utab->entries[i];      
03640           uentry old = usymtab_lookupAux (t, uentry_rawName (current));
03641 
03642           uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
03643         }
03644     }
03645 
03646   llassert (t != NULL);
03647 
03648   if (t->lexlevel > paramsScope)
03649     {
03650       t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
03651       t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases, 
03652                                              t->lexlevel);
03653       utab->aliases = aliasTable_undefined;
03654     }
03655 
03656   t->mustBreak = utab->mustBreak;
03657   t->exitCode = utab->exitCode;
03658 
03659   usymtab_freeLevel (utab);
03660 
03661   utab = t;
03662 }
03663 
03664 /*
03665 ** Exit a scope with no checking, lose alias states.
03666 ** (When should this be used?)
03667 */
03668 
03669 void usymtab_quietPlainExitScope (void)
03670      /*@globals utab, globtab, filetab@*/
03671      /*@modifies utab@*/
03672 {
03673   usymtab t = utab->env;
03674 
03675   llassert (t != NULL);
03676   llassert (NOALIAS (utab->aliases, t->aliases));
03677   usymtab_freeLevel (utab);
03678   utab = t;
03679 }
03680 
03681 void usymtab_exitScope (exprNode expr)
03682   /*@globals utab, filetab, globtab@*/
03683   /*@modifies utab, globtab@*/
03684 {
03685   usymtab ctab = usymtab_undefined;
03686   usymtab lctab = usymtab_undefined;
03687   bool mustReturn = exprNode_mustEscape (expr);
03688   
03689   if (utab->kind == US_CBRANCH)
03690     {
03691       /*
03692       ** save the case branches, remove the first non-cbranch
03693       */
03694 
03695       ctab = utab;
03696 
03697       while (utab->kind == US_CBRANCH) 
03698         {
03699           lctab = utab;
03700           utab = utab->env;
03701           llassert (utab != GLOBAL_ENV);
03702         }
03703     }
03704   
03705   if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
03706       || utab->kind == US_CBRANCH || utab->kind == US_SWITCH) {
03707    
03708     if (context_inMacro ()) {
03709       /* evs 2000-07-25 */
03710       /* Unparseable macro may end inside nested scope.  Deal with it. */
03711       
03712       llerror (FLG_SYNTAX, message ("Problem parsing macro body of %s (unbalanced scopes).  Attempting to recover, recommend /*@notfunction@*/ before macro definition.", 
03713                                     context_inFunctionName ()));
03714       
03715       while (utab->kind == US_TBRANCH
03716              || utab->kind == US_FBRANCH
03717              || utab->kind == US_CBRANCH
03718              || utab->kind == US_SWITCH) 
03719         {
03720           utab = utab->env;
03721           llassert (utab != GLOBAL_ENV);
03722         }
03723     } else {
03724       llcontbug (("exitScope: in branch: %s", usymtab_unparseStack ()));
03725       /*@-branchstate@*/ 
03726     } /*@=branchstate@*/
03727   }
03728 
03729   /*
03730   ** check all variables in scope were used
03731   */
03732 
03733   /*
03734   ** bogus errors if this is the normal inside a switch,
03735   ** since cases have not been merged yet.  Should probably
03736   ** still check this, but I'm too lazy at the moment...
03737   */
03738 
03739   llassertfatal (utab->env != GLOBAL_ENV);
03740 
03741   if (utab->env->kind != US_SWITCH)
03742     {
03743       usymtab_allUsed ();
03744     }
03745 
03746   /*
03747   ** check aliasing: all only params are released (dead)
03748   **     definition: all out params are defined, all modified params 
03749   **                     are completely defined
03750   **
03751   ** NOTE: note for exiting paramsScope, since checkReturn should be
03752   ** called first.
03753   */
03754 
03755   if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
03756     {
03757       /*
03758       ** should only call this is end of scope is reachable...
03759       */
03760 
03761       usymtab_checkFinalScope (FALSE);
03762     }
03763 
03764   if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
03765     {
03766       /*
03767       ** leaving a function, need to fix up globals
03768       */
03769 
03770       uentryList params = context_getParams ();
03771       globSet    globs = context_getUsedGlobs ();
03772 
03773                   
03774       uentryList_elements (params, ue)
03775         {
03776           uentry_fixupSref (ue);
03777         } end_uentryList_elements;
03778 
03779       clearFunctionTypes ();
03780 
03781       
03782       globSet_allElements (globs, el)
03783         {
03784           if (sRef_isCvar (el))
03785             {
03786               uentry current;
03787               int index = sRef_getScopeIndex (el);
03788               
03789               if (sRef_isFileStatic (el))
03790                 {
03791                   llassert (usymtab_isDefined (filetab));
03792                   current = usymtab_fetchIndex (filetab, index);
03793                 }
03794               else
03795                 {
03796                   current = usymtab_fetchIndex (globtab, index);
03797                 }
03798               
03799               if (uentry_isVariable (current))
03800                 {
03801                   uentry_fixupSref (current);
03802                 }
03803               else
03804                 {
03805                   sRef_clearDerived (uentry_getSref (current));
03806                 }
03807             }
03808         } end_globSet_allElements;
03809     }
03810   
03811   usymtab_quietExitScope (exprNode_loc (expr));
03812   
03813   if (lctab != usymtab_undefined)
03814     {
03815       /*@i@*/ lctab->env = utab;  
03816       /*@i@*/ utab = ctab;
03817     /*@-branchstate@*/ } /*@=branchstate@*/
03818 /*@-globstate@*/
03819 }
03820 /*@=globstate@*/
03821 
03822 /*
03823 ** yikes!  don't let the '170 kids see this one...
03824 */
03825 
03826 int
03827 uentry_directParamNo (uentry ue)
03828 {
03829   if (uentry_isVar (ue))
03830     {
03831       sRef sr = uentry_getSref (ue);
03832 
03833       if (sRef_lexLevel (sr) == functionScope)
03834         {
03835           /*@access sRef@*/ /*@-null@*/
03836           int index = sr->info->cvar->index;
03837           /*@noaccess sRef@*/ /*@=null@*/
03838 
03839           if (index < uentryList_size (context_getParams ()))
03840             {
03841               return index;
03842             }
03843         }
03844     }
03845   return -1;
03846 }
03847 
03848 /*@dependent@*/ /*@exposed@*/ uentry
03849   usymtab_getParam (int paramno)
03850   /*@globals utab@*/
03851 {
03852   /*
03853   ** requires in a function context (checked)
03854   **
03855   ** depends on no nested functions --- the function
03856   ** parameters are ALWAYS one scope inside the global scope
03857   ** and entered in order!
03858   */
03859   usymtab s = utab;
03860 
03861   if (!context_inFunctionLike ())
03862     llfatalbug (message ("usymtab_getParam: not in function context: %q", 
03863                          context_unparse ()));
03864 
03865   while (s->lexlevel > paramsScope) 
03866     {
03867       s = s->env;
03868     }
03869 
03870   llassert (usymtab_isDefined (s));
03871 
03872   if (paramno >= s->nentries)
03873     {
03874       /*  
03875       ** Parse errors lead to this. 
03876       */
03877 
03878       uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
03879                                            ctype_unknown);
03880       
03881       uentry_markOwned (err);
03882       return (err);
03883     }
03884 
03885   return (s->entries[paramno]);
03886 }
03887 
03888 static /*@dependent@*/ /*@exposed@*/ uentry 
03889 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
03890 {
03891   uentry ue;
03892 
03893   
03894   ue = usymtab_getRefNoisy (u, level, index);
03895 
03896   
03897   if (uentry_isUndefined (ue))
03898     {
03899       llbug (message ("usymtab_getRef: out of range: %d. level = %d",
03900                     index, level));
03901     }
03902 
03903   
03904   return ue;
03905 }
03906 
03907 static /*@dependent@*/ /*@exposed@*/ usymtab 
03908   usymtab_dropEnv (/*@notnull@*/ usymtab s)
03909 {
03910   if (s->kind == US_CBRANCH)
03911     {
03912       usymtab t = s;
03913 
03914       do 
03915         {
03916           t = s;
03917           s = s->env;
03918           llassert (s != GLOBAL_ENV);
03919         } while (s->kind == US_CBRANCH); 
03920       /* drop all cases (except in nested scopes */ 
03921 
03922       s = t;
03923       llassert (s != GLOBAL_ENV);
03924     }
03925 
03926   if (s->kind == US_FBRANCH)
03927     {
03928       s = s->env; /* skip the true branch */
03929       llassert (usymtab_isDefined (s));
03930       llassert (s->kind == US_TBRANCH);
03931     }
03932 
03933   llassert (s != GLOBAL_ENV);
03934   s = s->env;
03935 
03936   return s;
03937 }
03938 
03939 /*@dependent@*/ /*@exposed@*/ uentry
03940   usymtab_getRefQuiet (int level, usymId index)
03941   /*@globals utab@*/
03942 {
03943   usymtab s = utab;
03944   
03945   
03946   llassert (s != NULL);
03947   llassert (index >= 0);
03948 
03949   if (level > s->lexlevel)
03950     {
03951             
03952       return uentry_undefined;
03953     }
03954 
03955   llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d", 
03956                                         level, s->lexlevel)); 
03957 
03958   while (s->lexlevel > level)
03959     {
03960       if (usymtab_isBranch (s))
03961         {
03962           int eindex = refTable_lookup (s, level, index);
03963 
03964           if (eindex != NOT_FOUND)
03965             {
03966               return (s->entries[eindex]);
03967             }
03968         }
03969 
03970       s = usymtab_dropEnv (s);
03971     }
03972 
03973   while (usymtab_isBranch (s) && s->lexlevel == level)
03974     {
03975       int eindex = refTable_lookup (s, level, index);
03976       
03977       if (eindex != NOT_FOUND)
03978         {
03979           return (s->entries[eindex]);
03980         }
03981 
03982       s = usymtab_dropEnv (s);
03983     }
03984  
03985   if (index >= s->nentries)
03986     {
03987       return uentry_undefined;
03988     }
03989 
03990   llassert (!uentry_isUndefined (s->entries[index]));
03991 
03992   return s->entries[index];
03993 }
03994 
03995 static /*@dependent@*/ /*@exposed@*/ uentry
03996 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
03997 {
03998   usymtab otab = s;
03999   uentry ue = uentry_undefined;
04000 
04001   
04002   llassert (index >= 0);
04003 
04004   
04005   while (s->lexlevel > level)
04006     {
04007       
04008       if (usymtab_isBranch (s))
04009         {
04010           int eindex = refTable_lookup (s, level, index);
04011 
04012           if (eindex != NOT_FOUND)
04013             {
04014               ue = s->entries[eindex];
04015 
04016               if (s != otab)
04017                 {
04018                   while (!usymtab_isBranch (otab))
04019                     {
04020                       otab = usymtab_dropEnv (otab);
04021                       llassert (otab != GLOBAL_ENV);
04022                     }
04023                 
04024                   if (refTable_lookup (otab, level, index) == NOT_FOUND)
04025                     {
04026                       ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
04027                     }
04028                   else
04029                     {
04030                       ;
04031                     }
04032                 }
04033               
04034               return ue;
04035             }
04036         }
04037 
04038       s = usymtab_dropEnv (s);
04039     }
04040 
04041   llassert (usymtab_isDefined (s));
04042 
04043   while (usymtab_isBranch (s) && s->lexlevel == level)
04044     {
04045       int eindex = refTable_lookup (s, level, index);
04046 
04047       
04048       if (eindex != NOT_FOUND)
04049         {
04050           ue = s->entries[eindex];
04051           
04052           if (s != otab)
04053             {
04054               while (!usymtab_isBranch (otab))
04055                 {
04056                   otab = usymtab_dropEnv (otab);
04057                   llassert (otab != GLOBAL_ENV);
04058                 }
04059 
04060               ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
04061             }
04062           else
04063             {
04064               ;
04065             } 
04066 
04067           return ue;
04068         }
04069 
04070       s = usymtab_dropEnv (s);
04071           }
04072 
04073   if (s->lexlevel == level && (index < s->nentries))
04074     {
04075       ue = s->entries[index];
04076       
04077       if (uentry_isValid (ue))
04078         {
04079           if (s != otab)
04080             {
04081               while (!usymtab_isBranch (otab))
04082                 {
04083                   otab = usymtab_dropEnv (otab);
04084                   
04085                   if (otab == GLOBAL_ENV)
04086                     {
04087                       return ue;
04088                     }
04089                 }
04090               
04091               ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
04092             }
04093           else
04094             {
04095                     }
04096         }
04097 
04098       return ue;
04099     }
04100 
04101   
04102   if (index >= s->nentries)
04103     {
04104       return uentry_undefined;
04105     }
04106 
04107   llassert (!uentry_isUndefined (s->entries[index]));
04108 
04109   return s->entries[index];
04110 }
04111 
04112 /*
04113 ** looking up entries
04114 **
04115 ** If entry is inside a branch, then copy it, and put it into 
04116 ** the branch table.
04117 */
04118 
04119 static
04120 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
04121 {
04122   refTable rt = ut->reftable;
04123   int i;
04124 
04125   llassert (rt != NULL);
04126 
04127   
04128   for (i = 0; i < ut->nentries; i++)
04129     {
04130       if (rt[i]->level == level && rt[i]->index == index)
04131         {
04132                   return i;
04133         }
04134     }
04135 
04136     return NOT_FOUND;
04137 }
04138   
04139 static
04140 /*@only@*/ refentry refentry_create (int level, int index)
04141 {
04142   refentry r = (refentry) dmalloc (sizeof (*r));
04143 
04144   r->level = level;
04145   r->index = index;
04146 
04147   return r;
04148 }
04149 
04150 static /*@dependent@*/ /*@exposed@*/ uentry
04151 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
04152 {
04153   int eindex;
04154   usymtab ut = s;
04155 
04156   llassert (ut->reftable != NULL);
04157 
04158   while (s != GLOBAL_ENV)
04159     {
04160       eindex = usymtab_getIndex (s, k);
04161       
04162       if (eindex != NOT_FOUND)
04163         {
04164           uentry current = s->entries[eindex];
04165 
04166           if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
04167             {
04168               uentry ue;
04169 
04170               DPRINTF (("Here: copying %s", uentry_unparseFull (current)));
04171 
04172               ue = uentry_copy (current);
04173 
04174               DPRINTF (("Here: copying %s", uentry_unparseFull (ue)));
04175 
04176               usymtab_addEntryQuiet (ut, ue);
04177 
04178               if (s->reftable != NULL)
04179                 {
04180                   refentry ref = s->reftable[eindex];
04181 
04182                   
04183                   ut->reftable[ut->nentries - 1] 
04184                     = refentry_create (ref->level, ref->index);
04185                 }
04186               else
04187                 {
04188                   ut->reftable[ut->nentries - 1] 
04189                     = refentry_create (s->lexlevel, eindex);
04190                 }
04191               
04192               return (ue);
04193             }
04194           else
04195             {
04196               return (current);
04197             }
04198         }
04199 
04200       s = usymtab_dropEnv (s);
04201     }
04202 
04203   return uentry_undefined;
04204 }
04205 
04206 static uentry usymtab_lookupAux (usymtab s, cstring k)
04207 {
04208   DPRINTF (("Lookup: %s", k));
04209 
04210   while (s != GLOBAL_ENV)
04211     {
04212       int eindex = usymtab_getIndex (s, k);
04213 
04214       if (eindex != NOT_FOUND)
04215         {
04216           uentry ret = s->entries[eindex];
04217           
04218           DPRINTF (("Found: %s", uentry_unparseFull (ret)));
04219           return (ret);
04220         }
04221 
04222       if (s->kind == US_TBRANCH || s->kind == US_FBRANCH 
04223           || s->kind == US_CBRANCH)
04224         {
04225           uentry ret = usymtab_addRefEntry (s, k);
04226           DPRINTF (("Ref entry: %s", uentry_unparseFull (ret)));
04227           return ret;
04228         }
04229       
04230       s = s->env;
04231     }
04232   
04233   return uentry_undefined;
04234 }
04235 
04236 static /*@dependent@*/ /*@exposed@*/ uentry
04237 usymtab_lookupQuiet (usymtab s, cstring k)
04238 {
04239   int eindex;
04240 
04241   while (s != GLOBAL_ENV)
04242     {
04243       eindex = usymtab_getIndex (s, k);
04244       
04245       if (eindex != NOT_FOUND)
04246         {
04247           uentry ret = s->entries[eindex];
04248           return (ret);
04249         }
04250       
04251       s = s->env;
04252     }
04253 
04254   return uentry_undefined;
04255 }
04256 
04257 /*@dependent@*/ /*@observer@*/ uentry
04258   usymtab_lookupSafe (cstring k)
04259   /*@globals utab@*/
04260 {
04261   DPRINTF (("Lookup safe: %s", k));
04262   return (usymtab_lookupAux (utab, k));
04263 }
04264 
04265 uentry
04266   usymtab_lookupExpose (cstring k)
04267   /*@globals utab@*/
04268 {
04269   uentry ce = usymtab_lookupAux (utab, k);
04270 
04271   if (uentry_isUndefined (ce))
04272     {
04273       llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
04274     }
04275 
04276   if (uentry_isPriv (ce))
04277     {
04278       llfatalbug (message ("usymtab_lookup: private: *%s*", k));
04279     }
04280 
04281   return ce;
04282 }
04283 
04284 uentry usymtab_lookupExposeGlob (cstring k)
04285 {
04286   return (usymtab_lookupGlobSafe (k));
04287 }
04288 
04289 uentry usymtab_lookupGlob (cstring k)
04290   /*@globals globtab@*/
04291 {
04292   uentry ce = usymtab_lookupAux (globtab, k);
04293 
04294   if (uentry_isUndefined (ce))
04295     llfatalbug (message ("usymtab_lookup: not found: %s", k));
04296 
04297   if (uentry_isPriv (ce))
04298     llfatalbug (message ("usymtab_lookup: private: %s", k));
04299 
04300   return ce;
04301 }
04302 
04303 /*@observer@*/ uentry
04304   usymtab_lookupGlobSafe (cstring k)
04305   /*@globals globtab@*/
04306 {
04307   uentry ce = usymtab_lookupAux (globtab, k);
04308 
04309   return ce;
04310 }
04311 
04312 uentry usymtab_lookupEither (cstring k)
04313    /*@globals utab@*/
04314 {
04315   uentry ce = usymtab_lookupSafe (k);
04316 
04317   if (uentry_isUndefined (ce))
04318     llfatalerror (message ("usymtab_lookup: not found: %s", k));
04319 
04320   return ce;
04321 }
04322 
04323 # ifndef NOLCL
04324 ctype
04325 usymtab_lookupType (cstring k)
04326    /*@globals globtab@*/
04327 {
04328   usymId uid = usymtab_getTypeId (k);
04329 
04330   if (uid == USYMIDINVALID)
04331     {
04332       llcontbug (message ("usymtab_lookupType: not found: %s", k));
04333       return ctype_unknown;
04334     }
04335   
04336   return (uentry_getRealType (usymtab_getTypeEntry (uid)));
04337 }
04338 # endif
04339 
04340 ctype
04341 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
04342 {
04343   usymId uid = usymtab_getTypeId (k);
04344 
04345   if (uid == USYMIDINVALID)
04346     {
04347       llcontbug (message ("usymtab_lookupType: not found: %s", k));
04348       return ctype_unknown; 
04349     }
04350   
04351   return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
04352 }
04353   
04354 /*
04355 ** if there is an unnamed lcl-specified struct tag matching
04356 ** the uentryList, return its datatype.  Otherwise, returns
04357 ** ctype_undefined.
04358 */
04359 
04360 ctype
04361 usymtab_structFieldsType (uentryList f)
04362    /*@globals globtab@*/
04363 {
04364   return (usymtab_suFieldsType (f, TRUE));
04365 }
04366 
04367 ctype
04368 usymtab_unionFieldsType (uentryList f)
04369    /*@globals globtab@*/
04370 {
04371   return (usymtab_suFieldsType (f, FALSE));
04372 }
04373 
04374 static ctype
04375 usymtab_suFieldsType (uentryList f, bool isStruct)
04376   /*@globals globtab@*/
04377 {
04378   int i;
04379 
04380   if (fileloc_isSpec (g_currentloc)) return (ctype_undefined);
04381 
04382   for (i = 0; i < globtab->nentries; i++)
04383     {
04384       uentry current = globtab->entries[i];
04385 
04386       if ((isStruct 
04387            ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
04388         {
04389           if (isFakeTag (uentry_rawName (current)))
04390             {
04391               ctype ct = uentry_getType (current);
04392 
04393               if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
04394                   && (uentryList_matchFields (f, ctype_getFields (ct))))
04395                 {
04396                                   return uentry_getAbstractType (current);
04397                 }
04398             }
04399         }
04400     }
04401   
04402     return ctype_undefined;
04403 }
04404 
04405 ctype
04406   usymtab_enumEnumNameListType (enumNameList f)
04407   /*@globals globtab@*/
04408 {
04409   int i;
04410 
04411   for (i = 0; i < globtab->nentries; i++)
04412     {
04413       uentry current = globtab->entries[i];
04414 
04415       if (uentry_isEnumTag (current))
04416         {
04417           if (isFakeTag (uentry_rawName (current)))
04418             {
04419               ctype ct = uentry_getType (current);
04420 
04421               if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
04422                 {
04423                   return uentry_getType (current);
04424                 }
04425             }
04426         }
04427     }
04428   
04429   return ctype_undefined;
04430 }
04431 
04432 bool
04433 usymtab_exists (cstring k)
04434    /*@globals utab@*/
04435 {
04436   uentry ce = usymtab_lookupSafe (k);
04437 
04438   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
04439 }
04440 
04441 bool
04442 usymtab_existsReal (cstring k)
04443    /*@globals utab@*/
04444 {
04445   uentry ce = usymtab_lookupSafe (k);
04446 
04447   return (!(uentry_isUndefined (ce)) 
04448           && !(uentry_isPriv (ce))
04449           && !(uentry_isExpandedMacro (ce)));
04450 }
04451 
04452 bool
04453   usymtab_existsGlob (cstring k)
04454   /*@globals globtab@*/
04455 {
04456   uentry ce = usymtab_lookupAux (globtab, k);
04457 
04458   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
04459 }
04460 
04461 # ifndef NOLCL
04462 bool
04463 usymtab_existsEither (cstring k)
04464   /*@globals utab@*/
04465 {
04466   uentry ce = usymtab_lookupAux (utab, k);
04467   
04468   return (uentry_isValid (ce));
04469 }
04470 
04471 bool
04472   usymtab_existsGlobEither (cstring k)
04473   /*@globals globtab@*/
04474 {
04475   uentry ce = usymtab_lookupAux (globtab, k);
04476   
04477   return (uentry_isValid (ce));
04478 }
04479 # endif
04480 
04481 bool
04482 usymtab_existsType (cstring k)
04483   /*@globals globtab@*/
04484 {
04485   uentry ce = usymtab_lookupAux (globtab, k);
04486 
04487   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
04488 }
04489 
04490 bool
04491 usymtab_existsTypeEither (cstring k)
04492   /*@globals globtab@*/
04493 {
04494   uentry ce = usymtab_lookupAux (globtab, k);
04495 
04496     return (uentry_isValid (ce) && uentry_isDatatype (ce));
04497 }
04498 
04499 bool
04500 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
04501 {
04502   cstring sname = makeStruct (k);
04503   uentry ce = usymtab_lookupAux (globtab, sname);
04504 
04505   cstring_free (sname);
04506 
04507   
04508   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
04509 }
04510 
04511 bool
04512 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
04513 {
04514   cstring uname = makeUnion (k);
04515   uentry ce = usymtab_lookupAux (globtab, uname);
04516 
04517   cstring_free (uname);
04518 
04519   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
04520 }
04521 
04522 bool
04523 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
04524 {
04525   cstring ename = makeEnum (k);
04526   uentry ce = usymtab_lookupAux (globtab, ename);
04527 
04528   cstring_free (ename);
04529   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
04530 }
04531 
04532 # ifndef NOLCL
04533 bool usymtab_existsVar (cstring k)
04534    /*@globals utab@*/
04535 {
04536   uentry ce = usymtab_lookupSafe (k);
04537 
04538   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
04539 }
04540 # endif
04541 
04542 /*
04543 ** destructors
04544 */
04545 
04546 static void
04547 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
04548 {
04549   if (x != NULL)
04550     {
04551       int i;
04552 
04553       for (i = 0; i < nentries; i++)
04554         {
04555           sfree (x[i]);
04556         }
04557       
04558       sfree (x);
04559     }
04560 }
04561   
04562 static void
04563 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
04564   /*@globals globtab, utab, filetab@*/
04565 {
04566   int i;
04567 
04568   aliasTable_free (u->aliases);
04569 
04570   refTable_free (u->reftable, u->nentries);
04571 
04572   if (u == filetab || u == globtab)
04573     {
04574       for (i = 0; i < u->nentries; i++)
04575         {
04576           uentry_freeComplete (u->entries[i]);
04577         }
04578     }
04579   else
04580     {
04581       for (i = 0; i < u->nentries; i++)
04582         {
04583           uentry_free (u->entries[i]);
04584         }
04585     }
04586 
04587   guardSet_free (u->guards);
04588   sfree (u->entries);
04589 
04590   if (u != globtab 
04591       && u != utab
04592       && u != filetab)
04593     {
04594       llassert (u->htable == NULL);
04595       sfree (u);
04596     }
04597 
04598 /*@-mustfree@*/
04599 } /*@=mustfree@*/
04600 
04601 static void
04602 usymtab_freeAux (/*@only@*/ usymtab u)
04603    /*@globals globtab, utab, filetab@*/
04604    /*@modifies u@*/
04605 {
04606   while (u != GLOBAL_ENV)
04607     {
04608       usymtab t = u->env;
04609       usymtab_freeLevel (u);
04610       u = t;
04611       /*@-branchstate@*/ 
04612     } 
04613   /*@=branchstate@*/
04614 }
04615 
04616 void usymtab_free () 
04617   /*@globals killed utab, globtab, filetab@*/ 
04618   /*@modifies utab@*/
04619 {
04620   dbgfree = TRUE;
04621   usymtab_freeAux (utab);
04622 }
04623 
04624 static int usymtab_lexicalLevel (void) /*@globals utab@*/
04625 {
04626   return (utab->lexlevel);
04627 }
04628 
04629 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
04630 {
04631   return (utab == globtab);
04632 }
04633 
04634 bool usymtab_inFileScope () /*@globals utab@*/
04635 {
04636   return (utab->lexlevel == fileScope);
04637 }
04638 
04639 bool usymtab_inFunctionScope () /*@globals utab@*/
04640 {
04641   return (utab->lexlevel == functionScope);
04642 }
04643 
04644 # ifndef NOLCL
04645 void
04646 usymtab_replaceEntry (uentry s)
04647   /*@globals utab, globtab@*/
04648   /*@modifies utab, s@*/
04649 {
04650   usymtab_replaceEntryAux (utab, s);
04651 }
04652 # endif
04653 
04654 bool
04655 usymtab_matchForwardStruct (usymId u1, usymId u2)
04656    /*@globals globtab@*/
04657 {
04658   uentry ue1 = usymtab_getTypeEntry (u1);
04659   uentry ue2 = usymtab_getTypeEntry (u2);
04660 
04661   if (uentry_isAnyTag (ue2))
04662     {
04663       ctype reptype = uentry_getType (ue1);
04664       
04665       if (ctype_isPointer (reptype))
04666         {
04667           ctype repbase = ctype_getBaseType (reptype);
04668   
04669           if (ctype_isUA (repbase))
04670             {
04671               typeId rtuid = ctype_typeId (repbase);
04672 
04673               if (u2 == rtuid) return TRUE;
04674               
04675               if (usymId_isValid (rtuid))
04676                 {
04677                   reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
04678                   
04679                   return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
04680                 }
04681             }
04682         }
04683     }
04684   
04685   return FALSE;
04686 }
04687 
04688 void usymtab_addGuards (guardSet guards)
04689   /*@modifies utab@*/
04690 {
04691   utab->guards = guardSet_union (utab->guards, guards);
04692   }
04693 
04694 static bool usymtab_isGuardedAux (sRef s)
04695   /*@globals utab@*/
04696 {
04697   usymtab tab = utab;
04698   sRef base = sRef_getRootBase (s);
04699   int lowlevel = paramsScope;
04700   int baselevel = sRef_lexLevel (base);
04701 
04702   if (sRef_isCvar (base))
04703     {
04704       lowlevel = baselevel;
04705       if (lowlevel < paramsScope) lowlevel = paramsScope;
04706     }
04707   
04708   while (tab->lexlevel >= lowlevel)
04709     {
04710       if (guardSet_isGuarded (tab->guards, s))
04711         {
04712           /*
04713           if (!sRef_definitelyNull (s))
04714             {
04715               sRef_setNotNull (s, fileloc_undefined);
04716             }
04717             */
04718           return TRUE;
04719         }
04720 
04721       tab = usymtab_dropEnv (tab);
04722     }
04723   
04724   return FALSE;
04725 }
04726 
04727 void usymtab_unguard (sRef s) /*@modifies utab@*/
04728 {
04729   usymtab tab = utab;
04730   sRef base = sRef_getRootBase (s);
04731   int lowlevel = paramsScope;
04732   int baselevel = sRef_lexLevel (base);
04733   
04734   if (sRef_isCvar (base))
04735     {
04736       lowlevel = baselevel;
04737       if (lowlevel < paramsScope) lowlevel = paramsScope;
04738     }
04739 
04740   while (tab->lexlevel >= lowlevel)
04741     {
04742       if (guardSet_isGuarded (tab->guards, s))
04743         {
04744           guardSet_delete (tab->guards, s);
04745         }
04746       
04747       tab = usymtab_dropEnv (tab);
04748     }
04749 }
04750 
04751 bool usymtab_isGuarded (sRef s)
04752 {
04753   
04754   return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
04755 }
04756 
04757 bool usymtab_isProbableNull (sRef s)
04758 {
04759   return (sRef_aliasCheckSimplePred (usymtab_isProbableNullAux, s));
04760 }
04761 
04762 bool usymtab_isProbableDeepNull (sRef s)
04763 {
04764   return (sRef_deepPred (usymtab_isProbableNull, s));
04765 }
04766 
04767 static bool usymtab_isProbableNullAux (sRef s)
04768   /*@globals utab@*/
04769 {
04770   usymtab tab = utab;
04771   sRef base = sRef_getRootBase (s);
04772   int  lowlevel = paramsScope;
04773   
04774   if (sRef_isCvar (base))
04775     {
04776       lowlevel = sRef_lexLevel (base);
04777       if (lowlevel < paramsScope) lowlevel = paramsScope;
04778     }
04779   
04780   while (tab->lexlevel >= lowlevel)
04781     {
04782       if (guardSet_isProbableNull (tab->guards, s))
04783         {
04784           return TRUE;
04785         }
04786       
04787       while (tab->kind == US_CBRANCH) 
04788         {
04789           tab = tab->env;
04790         }
04791 
04792       llassert (usymtab_isDefined (tab));
04793 
04794       if (tab->kind == US_FBRANCH)
04795         {
04796           tab = tab->env;
04797           llassert (tab->kind == US_TBRANCH);
04798         }
04799       
04800       tab = tab->env;
04801     }
04802 
04803   return FALSE;
04804 }
04805 
04806 void
04807 usymtab_printGuards ()
04808   /*@globals utab, globtab@*/
04809 {
04810   usymtab ttab = utab;
04811 
04812   while (ttab != globtab)
04813     {
04814       llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
04815                       guardSet_unparse (ttab->guards)));
04816       ttab = ttab->env;
04817     }
04818 }
04819 
04820 void
04821 usymtab_displayAllUses ()
04822   /*@globals utab, globtab@*/
04823 {
04824   usymtab copy;
04825 
04826   /* only in top scope */
04827   llassert (utab == globtab);
04828 
04829   /* need a copy, so order is not messed up by sort! */  
04830   copy = usymtab_shallowCopy (globtab); 
04831   
04832   qsort (copy->entries, (size_t)copy->nentries, 
04833          sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
04834 
04835   usymtab_entries (copy, ue)
04836     {
04837       if (uentry_isValid (ue))
04838         {
04839           filelocList uses = uentry_getUses (ue);
04840           int size = filelocList_realSize (uses);
04841 
04842           if (fileloc_isDefined (uentry_whereDefined (ue)) 
04843               && !fileloc_isLib (uentry_whereDefined (ue))
04844               && (size > 0))
04845             {
04846               llmsg (message ("%q (%q), %d use%p:\n   %q", 
04847                               uentry_getName (ue),
04848                               fileloc_unparse (uentry_whereDefined (ue)),
04849                               size, filelocList_unparseUses (uses)));
04850             }
04851         }
04852     } end_usymtab_entries;
04853   
04854   usymtab_shallowFree (copy);
04855 }
04856 
04857 static /*@dependent@*/ /*@exposed@*/ usymtab
04858 usymtab_getFileTab ()
04859   /*@globals filetab@*/
04860 {
04861   llassert (filetab != NULL);
04862 
04863   return filetab;
04864 }
04865 
04866 /*@only@*/ cstring
04867 usymtab_unparseStack ()
04868   /*@globals utab@*/
04869 {
04870   return (usymtab_unparseStackTab (utab));
04871 }
04872  
04873 static /*@only@*/ cstring
04874 usymtab_unparseStackTab (usymtab t)
04875 {
04876   bool firstOne = TRUE;
04877   cstring ret = cstring_makeLiteral ("[");
04878 
04879   while (t != GLOBAL_ENV)
04880     {
04881       if (firstOne)
04882         {
04883           ret = message ("%q %q", ret, usymtab_typeName (t));
04884           firstOne = FALSE;
04885         }
04886       else
04887         {
04888           ret = message ("%q, %q", ret, usymtab_typeName (t));
04889         }
04890       t = t->env;
04891     }
04892 
04893   ret = message ("%q ]", ret);
04894   return ret;
04895 }
04896 
04897 static /*@only@*/ cstring
04898 usymtab_typeName (/*@notnull@*/ usymtab t)
04899 {
04900   switch (t->kind)
04901     {
04902     case US_GLOBAL:  return cstring_makeLiteral ("global");
04903     case US_NORMAL:  return cstring_makeLiteral ("normal");
04904     case US_TBRANCH: return cstring_makeLiteral ("true");
04905     case US_FBRANCH: return cstring_makeLiteral ("false");
04906     case US_CBRANCH: return cstring_makeLiteral ("case");
04907     case US_SWITCH:  return cstring_makeLiteral ("switch");
04908     }
04909   
04910   BADEXIT;
04911 }
04912 
04913 void usymtab_addMustAlias (sRef s, sRef al)
04914   /*@modifies utab@*/
04915 {
04916   if (sRef_isMeaningful (s) && sRef_isMeaningful (al)
04917       && !(sRef_isConst (s) || sRef_isConst (al))
04918       && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al)))
04919       && !(sRef_similar (s, al)))
04920     {
04921       utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al); 
04922       DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
04923 
04924       /*
04925       ** for local variable, aliasing is symmetric 
04926       */
04927       
04928       if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
04929         {
04930           utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s); 
04931         }
04932     }
04933   else
04934     {
04935       ;
04936     }
04937 }
04938 
04939 /*
04940 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
04941 */
04942 
04943 void usymtab_addForceMustAlias (sRef s, sRef al)
04944   /*@modifies utab@*/
04945 {
04946   if (sRef_isMeaningful (s) 
04947       && sRef_isMeaningful (al)
04948       && !(sRef_isConst (s) || sRef_isConst (al))
04949       && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
04950     {
04951       utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al); 
04952       DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
04953 
04954       /*
04955       ** for local variable, aliasing is symmetric 
04956       */
04957       
04958       if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
04959         {
04960           utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s); 
04961         }
04962     }
04963   else
04964     {
04965       ;
04966     }
04967 }
04968 
04969 void usymtab_clearAlias (sRef s)
04970   /*@modifies utab, s@*/
04971 {
04972   
04973   aliasTable_clearAliases (utab->aliases, s); 
04974 }
04975 
04976 sRefSet usymtab_allAliases (sRef s)
04977    /*@globals utab@*/  
04978 {
04979   if (sRef_isMeaningful (s))
04980     {
04981       sRefSet ret;
04982 
04983             
04984       ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
04985                                aliasTable_canAlias (utab->aliases, s));
04986             return (ret);
04987     }
04988   else
04989     {
04990       return sRefSet_undefined;
04991     }
04992 }
04993 
04994 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
04995   /*@globals utab@*/
04996 {
04997   if (sRef_isMeaningful (s))
04998     {
04999       sRefSet res = aliasTable_canAlias (utab->aliases, s);
05000 
05001       return res;
05002     }
05003 
05004   return sRefSet_undefined;
05005 }
05006 
05007 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
05008   /*@globals utab@*/
05009 {
05010   return (aliasTable_aliasedBy (utab->aliases, s));
05011 }
05012 
05013 /*@only@*/ cstring usymtab_unparseAliases ()
05014   /*@globals utab@*/
05015 {
05016   return (aliasTable_unparse (utab->aliases));
05017 }
05018 
05019 /*
05020 ** Debugging routines:
05021 **    okay to leak storage here, only for debugging 
05022 */
05023 
05024 /*@-mustfree@*/ 
05025 
05026 void
05027 usymtab_printOut (void)
05028   /*@globals utab@*/
05029 {
05030   int i;
05031   usymtab s = utab;
05032   int depth = 0;
05033   char *ind = mstring_copy ("               ");
05034 
05035   fprintf (g_msgstream, "<<< [symbol table] >>>\n");
05036   
05037   while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
05038     {
05039       cstring tname = usymtab_typeName (s);
05040 
05041       if (depth < 5)
05042         {
05043           ind[depth * 3 + 1] = '\0';
05044         }
05045      
05046       fprintf (g_msgstream, "level: %d (%s)\n", s->lexlevel,
05047                cstring_toCharsSafe (tname));
05048 
05049       cstring_free (tname);
05050 
05051       for (i = 0; i < s->nentries; i++)
05052         {
05053           cstring us = uentry_unparseFull (s->entries[i]);
05054           fprintf (g_msgstream, "%s\n", cstring_toCharsSafe (us));
05055           cstring_free (us);
05056         }
05057       
05058       if (s->reftable != NULL && s->nentries > 0)
05059         {
05060           fprintf (g_msgstream, "\t<< Ref table >>\n");
05061 
05062           for (i = 0; i < s->nentries; i++)
05063             {
05064               fprintf (g_msgstream, "\t%s %3d: %d, %d\n", ind, i, 
05065                        s->reftable[i]->level,
05066                        s->reftable[i]->index);
05067             }
05068         }
05069 
05070       ind[depth * 3 + 1] = ' ';
05071       depth++;
05072       s = s->env;
05073     }
05074   fprintf (g_msgstream, "<<< end usymtab >>>\n");
05075   mstring_free (ind);
05076   return;
05077 }
05078 
05079 void
05080 usymtab_printTypes ()
05081   /*@globals globtab@*/
05082 {
05083   usymtab_printAllAux (globtab);
05084 }
05085 
05086 void 
05087 usymtab_printAll (void)
05088   /*@globals utab@*/
05089 {
05090   usymtab_printAllAux (utab);
05091 }
05092 
05093 static void
05094 usymtab_printAllAux (usymtab s)
05095    /*@modifies g_msgstream@*/
05096 {
05097   int i;
05098   int depth = 0;
05099   char *ind = mstring_copy ("               ");
05100 
05101   printf ("[[[ usymtab ]]]");
05102 
05103   while (s != GLOBAL_ENV)
05104     {
05105       if (depth < 5)
05106         ind[depth * 3 + 1] = '\0';
05107       
05108       if (s->env == GLOBAL_ENV)
05109         {
05110           int looplow;
05111 
05112           printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
05113                   cstring_toCharsSafe (bool_unparse (s->mustBreak)), 
05114                   cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
05115 
05116           looplow = 0;
05117 
05118           for (i = looplow; i < s->nentries; i++)
05119             {
05120               printf ("%s%3d. %s\n", ind, i, 
05121                       cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
05122             }
05123         }
05124       else
05125         {
05126           printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
05127                   cstring_toCharsSafe (bool_unparse (s->mustBreak)),
05128                   cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
05129 
05130           for (i = 0; i < s->nentries; i++)
05131             {
05132               printf ("%s%3d %s\n", ind, i, 
05133                      cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
05134             }
05135         }
05136       
05137       ind[depth * 3 + 1] = ' ';
05138       depth++;
05139       s = s->env;
05140     }
05141   printf ("----------\n");
05142 }
05143 
05144 void
05145 usymtab_printComplete ()
05146   /*@globals utab@*/
05147 {
05148   int i;
05149   int depth = 0;
05150   char *ind = mstring_copy ("               ");
05151   usymtab s = utab;
05152 
05153   while (s != GLOBAL_ENV)
05154     {
05155       if (depth < 5)
05156         {
05157           ind[depth * 3 + 1] = '\0';
05158         }
05159       
05160       if (s->env == GLOBAL_ENV)
05161         {
05162           int looplow;
05163 
05164           printf ("level: %d\n", s->lexlevel);
05165 
05166           looplow = 0;
05167 
05168           for (i = looplow; i < s->nentries; i++)
05169             {
05170               printf ("%s%3d %s\n", ind, i, 
05171                       cstring_toCharsSafe (uentry_unparse (s->entries[i])));
05172             }
05173         }
05174       else
05175         {
05176           printf ("level: %d\n", s->lexlevel);
05177           for (i = 0; i < s->nentries; i++)
05178             {
05179               printf ("%s%3d %s\n", ind, i, 
05180                      cstring_toCharsSafe (uentry_unparse (s->entries[i])));
05181             }
05182         }
05183       
05184       ind[depth * 3 + 1] = ' ';
05185       depth++;
05186       s = s->env;
05187     }
05188 
05189   printf ("----------\n");
05190   mstring_free (ind);
05191 }
05192 
05193 static /*@only@*/ cstring /*@unused@*/ 
05194 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
05195 {
05196   cstring c = message ("lexlevel: %d\n", s->lexlevel);
05197   int i;
05198 
05199   for (i = 0; i < s->nentries; i++)
05200     {
05201       c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
05202     }
05203 
05204   c = message ("%q\n=========", c);
05205   return (c);
05206 }
05207 
05208 static cstring /*@unused@*/ /*@only@*/ 
05209 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
05210 {
05211   cstring c = message ("[%d/%s/%s] ", s->lexlevel, 
05212                        bool_unparse (s->mustBreak), 
05213                        exitkind_unparse (s->exitCode));
05214   int i;
05215 
05216   for (i = 0; i < s->nentries; i++)
05217     {
05218       sRef sr = uentry_getSref (s->entries[i]);
05219 
05220       if (i == 0)
05221         {
05222           c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]), 
05223                        sRef_isStateDefined (sr));
05224         }
05225       else
05226         {
05227           c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]), 
05228                        sRef_isStateDefined (sr));
05229         }
05230 
05231     }
05232 
05233   return (c);
05234 }
05235 
05236 void
05237 usymtab_printLocal (void)
05238   /*@globals utab@*/
05239 {
05240   int i;
05241   usymtab s = utab;
05242 
05243   printf ("lexlevel: %d\n", s->lexlevel);
05244 
05245   for (i = 0; i < s->nentries; i++)
05246     {
05247       printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
05248     }
05249   
05250   while (s->lexlevel > 1)
05251     {
05252       s = s->env;
05253     }
05254 
05255   llassert (usymtab_isDefined (s));
05256 
05257   printf ("Params:\n");
05258 
05259   for (i = 0; i < s->nentries; i++)
05260     {
05261       printf ("%d: %s\n", i, 
05262               cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
05263     }
05264 }
05265 /*@=mustfree@*/
05266 
05267 static bool checkDistinctExternalName (uentry e)
05268   /*@globals globtab@*/
05269   /*@modifies *g_msgstream@*/
05270 {
05271   int checklen = context_getValue (FLG_EXTERNALNAMELEN);
05272   bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
05273   bool gotone = FALSE;
05274   bool extras = FALSE;
05275   bool hasError = FALSE;
05276   cstring name = uentry_rawName (e);
05277   usymtab st = globtab;
05278 
05279   if (checklen == 0)
05280     {
05281       ;
05282     }
05283   else
05284     {
05285       if (uentry_isAnyTag (e)) 
05286         {
05287           checklen++;  /* the tag marker doesn't count */
05288         }
05289     }
05290 
05291   usymtab_entries (st, oe)
05292     {
05293       if (uentry_sameObject (oe, e))
05294         {
05295           continue;
05296         }
05297 
05298       if (checklen == 0)
05299         {
05300           if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
05301             {
05302               if (gotone)
05303                 {
05304                   extras = TRUE;
05305                   break;
05306                 }
05307               
05308               if (optgenerror 
05309                   (FLG_DISTINCTEXTERNALNAMES,
05310                    message 
05311                    ("External identifier %q is not distinguishable from %q "
05312                     "because alphabetical case is ignored",
05313                     uentry_getName (e),
05314                     uentry_getName (oe)),
05315                    uentry_whereLast (e)))
05316                 {
05317                   uentry_showWhereAny (oe);
05318                   uentry_setHasNameError (oe);
05319                   gotone = TRUE;
05320                 }
05321             }
05322         }
05323       else
05324         {
05325           if (ignorecase)
05326             {
05327               if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
05328                                                    name, checklen))
05329                 {
05330                   if (gotone)
05331                     {
05332                       extras = TRUE;
05333                       break;
05334                     }
05335                   
05336                   if (cstring_equalLen (uentry_rawName (oe), name, checklen))
05337                     {
05338                       if (optgenerror 
05339                           (FLG_DISTINCTEXTERNALNAMES,
05340                            /*@-sefparams@*/
05341                            message 
05342                            ("External identifier %q is not distinguishable from %q "
05343                             "in the first %d characters (%q)",
05344                             uentry_getName (e),
05345                             uentry_getName (oe),
05346                             checklen,
05347                             cstring_clip (uentry_getName (e), checklen)),
05348                            /*@=sefparams@*/
05349                            uentry_whereLast (e)))
05350                         {
05351                           uentry_showWhereAny (oe);
05352                           uentry_setHasNameError (oe);
05353                           gotone = TRUE;
05354                         }
05355                     }
05356                   else
05357                     {
05358                       if (gotone)
05359                         {
05360                           extras = TRUE;
05361                           break;
05362                         }
05363                       
05364                       if (optgenerror 
05365                           (FLG_DISTINCTEXTERNALNAMES,
05366                            message 
05367                            ("External identifier %q is not distinguishable from %q "
05368                             "in the first %d characters because alphabetical case "
05369                             "is ignored",
05370                             uentry_getName (e),
05371                             uentry_getName (oe),
05372                             checklen),
05373                            uentry_whereLast (e)))
05374                         {
05375                           uentry_showWhereAny (oe);
05376                           uentry_setHasNameError (oe);
05377                           gotone = TRUE;
05378                         }
05379                     }
05380                 }
05381             }
05382           else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
05383             {
05384               if (gotone)
05385                 {
05386                   extras = TRUE;
05387                   break;
05388                 }
05389               
05390               if (optgenerror 
05391                   (FLG_DISTINCTEXTERNALNAMES,
05392                    /*@-sefparams@*/
05393                    message 
05394                    ("External identifier %q is not distinguishable from %q "
05395                     "in the first %d characters (%q)",
05396                     uentry_getName (e),
05397                     uentry_getName (oe),
05398                     checklen,
05399                     cstring_clip (uentry_getName (e), checklen)),
05400                    /*@=sefparams@*/
05401                    uentry_whereLast (e)))
05402                 {
05403                   uentry_showWhereAny (oe);
05404                   uentry_setHasNameError (oe);
05405                   gotone = TRUE;
05406                 }
05407             }
05408           else
05409             {
05410               ; /* okay */
05411             }
05412         }
05413     } end_usymtab_entries ;
05414 
05415   hasError = gotone;
05416   
05417   if (extras)
05418     {
05419       llgenindentmsgnoloc
05420         (cstring_makeLiteral ("One or more additional "
05421                               "indistinguishable external "
05422                               "names not reported"));
05423     }
05424 
05425   return hasError;
05426 }
05427 
05428 static bool checkDistinctInternalName (uentry e)
05429   /*@globals utab@*/
05430   /*@modifies *g_msgstream@*/
05431 {
05432   usymtab ttab = utab;
05433   cstring name = uentry_rawName (e);
05434   int numchars = context_getValue (FLG_INTERNALNAMELEN);
05435   bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
05436   bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
05437 
05438   if (uentry_isAnyTag (e) && (numchars != 0))
05439     {
05440       numchars++;  /* the tag marker doesn't count */
05441     }
05442   
05443   while (usymtab_isDefined (ttab))
05444     {
05445       usymtab_entries (ttab, oe)
05446         {
05447           if (uentry_sameObject (oe, e))
05448             {
05449               /*@innercontinue@*/ continue;
05450             }
05451 
05452           switch (cstring_genericEqual
05453                   (name, uentry_rawName (oe),
05454                    numchars, caseinsensitive, lookalike))
05455             {
05456             case CGE_DISTINCT: /* okay */
05457               /*@switchbreak@*/ 
05458               break;
05459             case CGE_SAME:
05460               if (cstring_equal (name, uentry_rawName (oe)))
05461                 {
05462                   ; /* got a shadow error */
05463                 }
05464               else
05465                 {
05466                   if (optgenerror 
05467                       (FLG_DISTINCTINTERNALNAMES,
05468                        /*@-sefparams@*/
05469                        message 
05470                        ("Internal identifier %q is not distinguishable from %q "
05471                         "in the first %d characters (%q)",
05472                         uentry_getName (e),
05473                         uentry_getName (oe),
05474                         numchars,
05475                         cstring_clip (uentry_getName (e), numchars)),
05476                        /*@=sefparams@*/
05477                        uentry_whereLast (e)))
05478                     {
05479                       uentry_showWhereAny (oe);
05480                       uentry_setHasNameError (oe);
05481                       return TRUE;
05482                     }
05483                 }
05484               /*@switchbreak@*/
05485               break;
05486             case CGE_CASE:
05487               if (numchars == 0 
05488                   || (cstring_length (name) <= numchars))
05489                 {
05490                   if (optgenerror 
05491                       (FLG_DISTINCTINTERNALNAMES,
05492                        message 
05493                        ("Internal identifier %q is not distinguishable from %q "
05494                         "without case sensitivity",
05495                         uentry_getName (e),
05496                         uentry_getName (oe)),
05497                        uentry_whereLast (e)))
05498                     {
05499                       uentry_showWhereAny (oe);
05500                       uentry_setHasNameError (oe);
05501                       return TRUE;
05502                     }
05503                 }
05504               else 
05505                 {
05506                   if (optgenerror 
05507                       (FLG_DISTINCTINTERNALNAMES,
05508                        message 
05509                        ("Internal identifier %q is not distinguishable from %q "
05510                         "in the first %d characters without case sensitivity",
05511                         uentry_getName (e),
05512                         uentry_getName (oe),
05513                         numchars),
05514                        uentry_whereLast (e)))
05515                     {
05516                       uentry_showWhereAny (oe);
05517                       uentry_setHasNameError (oe);
05518                       return TRUE;
05519                     }
05520                 }
05521               /*@switchbreak@*/ 
05522               break;
05523             case CGE_LOOKALIKE:
05524               if (numchars == 0 
05525                   || (cstring_length (name) <= numchars))
05526                 {
05527                   if (optgenerror 
05528                       (FLG_DISTINCTINTERNALNAMES,
05529                        message 
05530                        ("Internal identifier %q is not distinguishable from %q "
05531                         "except by lookalike characters",
05532                         uentry_getName (e),
05533                         uentry_getName (oe)),
05534                        uentry_whereLast (e)))
05535                     {
05536                       uentry_showWhereAny (oe);
05537                       uentry_setHasNameError (oe);
05538                       return TRUE;
05539                     }
05540                 }
05541               else 
05542                 {
05543                   if (optgenerror 
05544                       (FLG_DISTINCTINTERNALNAMES,
05545                        message 
05546                        ("Internal identifier %q is not distinguishable from %q "
05547                         "in the first %d characters except by lookalike characters",
05548                         uentry_getName (e),
05549                         uentry_getName (oe),
05550                         numchars),
05551                        uentry_whereLast (e)))
05552                     {
05553                       uentry_showWhereAny (oe);
05554                       uentry_setHasNameError (oe);
05555                       return TRUE;
05556                     }
05557                 }
05558             }
05559         } end_usymtab_entries ;
05560       
05561       ttab = ttab->env;
05562     }
05563 
05564   return FALSE;
05565 }
05566 
05567 void usymtab_checkDistinctName (uentry e, int scope)
05568    /*@globals utab, globtab@*/
05569 {
05570   bool hasError = FALSE;
05571   fileloc where = uentry_whereLast (e);
05572 
05573   if (!fileloc_isPreproc (where)  && !fileloc_isBuiltin (where))
05574     {
05575       if (scope == globScope)
05576         {
05577           if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
05578             {
05579               hasError = checkDistinctExternalName (e);
05580             }
05581         }
05582       
05583       if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
05584         {
05585           hasError = checkDistinctInternalName (e);
05586         }
05587     }
05588 
05589   if (hasError)
05590     {
05591             uentry_setHasNameError (e);
05592     }
05593 }
05594 

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