]> andersk Git - splint.git/blob - src/usymtab.c
Readded files.
[splint.git] / src / usymtab.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 ** 
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** General Public License for more details.
15 ** 
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
19 **
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
23 */
24 /*
25 ** usymtab
26 **
27 ** Lexically scoped symbol table.
28 **
29 ** Unlike a normal symbol table, this table splits to reflect branches.
30 **
31 ** This is necessary since symbol table entries also reflect
32 ** some state information, like initialization, that may be
33 ** different on different branches.
34 **
35 ** For each control structure we split:
36 **
37 ** { }                - a normal scope (no control) US_NORMAL
38 **
39 ** if <pred> { }      - US_TBRANCH true branch
40 ** while <pred> { }     US_FBRANCH else branch
41 **
42 ** switch <pred> { }  - US_SWITCH
43 **
44 ** case x:            - case scope US_CBRANCH
45 **                      Should be kept in a separate table, because of
46 **                      weird C syntax.
47 */
48
49 # include "lclintMacros.nf"
50 # include "basic.h"
51 # include "structNames.h"
52 # include "exprChecks.h"
53 # include "aliasChecks.h"
54
55 /*
56 ** Keep track of type definitions inside a function.
57 */
58
59 static uentryList functypes = uentryList_undefined;
60
61 static bool dbgfree = FALSE;
62 static bool dbgload = TRUE;
63
64 /*@access ekind usymId@*/
65
66 /*
67 ** Hack to prevent shadow errors from appearing when function parameters
68 ** are entered into a new scope.
69 */
70
71 static bool noshadowerror = FALSE;
72
73 /*
74 ** Constraint: static variables can live in 1 or > 2. 
75 **
76 ** except for tags.  All tags must be at the global level.
77 ** Static tags are handled in a kludgey way.
78 */
79
80 /*
81 ** utab    is the universal symbol table
82 ** globtab is the global environment of utab
83 ** oldtab  is needed for conversions in dumping (after sorting the table)
84 **
85 ** there can be only one usymtab!
86 */
87
88 static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
89
90 /* Reachable environments from from utab */
91 static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
92 static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
93
94 /* Used for sorting for dumpage. */
95 static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
96
97 static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
98 static bool usymtab_isProbableNullAltBranch (sRef p_s) /*@globals utab@*/ ;
99 static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
100 static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
101
102 static void
103 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
104   /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
105
106 static bool usymtab_isProbableNullAux (sRef p_s) /*@globals utab@*/ ;
107 static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
108 static /*@exposed@*/ /*@dependent@*/ uentry 
109   usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
110 static /*@unused@*/ /*@only@*/ cstring 
111   usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
112 static /*@unused@*/ /*@only@*/ cstring 
113   usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
114 static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
115 static void usymtab_handleParams (void)
116    /*@globals utab, globtab, filetab@*/ 
117    /*@modifies utab@*/ ;
118
119 static /*@exposed@*/ /*@dependent@*/ uentry 
120   usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
121 static /*@exposed@*/ /*@dependent@*/ usymtab
122   usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
123 static /*@exposed@*/ /*@dependent@*/ uentry 
124   usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
125
126 static /*@exposed@*/ /*@dependent@*/ uentry 
127   usymtab_lookupQuiet (usymtab p_s, cstring p_k);
128 static void usymtab_printAllAux (usymtab p_s) /*@modifies g_msgstream@*/ ;
129 static int usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
130 static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, int p_i);
131 static /*@exposed@*/ uentry 
132   usymtab_lookupAux (usymtab p_s, cstring p_k);
133 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/ usymtab 
134   usymtab_getFileTab (void) /*@globals filetab@*/ ;
135 static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, int p_index);
136 static bool usymtab_mustBreak (usymtab p_s);
137 static bool usymtab_mustEscape (usymtab p_s);
138
139 static void recordFunctionType (uentry ue)
140 {
141     llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
142             || uentry_isEnumConstant (ue));
143
144   /*@-temptrans@*/
145   functypes = uentryList_add (functypes, ue);
146   /*@=temptrans@*/
147 }
148
149 static void clearFunctionTypes (void)
150   /*@modifies globtab@*/
151 {
152   uentryList_elements (functypes, el)
153     {
154       if (cstring_isDefined (uentry_rawName (el)))
155         {
156           if (globtab->htable != NULL)
157             {
158               hashTable_remove (globtab->htable, uentry_rawName (el));
159             }
160
161           uentry_setName (el, cstring_undefined);
162         }
163
164       /*@access uentry@*/ 
165       llassert (uentry_isValid (el));
166       el->sref = sRef_undefined;
167       /*@noaccess uentry@*/
168     } end_uentryList_elements ;
169
170   uentryList_clear (functypes);
171 }
172
173 static /*@falsenull@*/ bool usymtab_isBranch (usymtab u)
174 {
175   return (usymtab_isDefined (u) && 
176           (u->kind == US_TBRANCH || u->kind == US_FBRANCH
177            || u->kind == US_CBRANCH || u->kind == US_SWITCH));
178 }
179
180 static bool usymtab_mustBreak (usymtab s)
181 {
182   llassert (s != GLOBAL_ENV);
183   return (s->mustBreak);
184 }
185
186 static bool usymtab_mustEscape (usymtab s)
187 {
188   llassert (s != GLOBAL_ENV);
189   return (exitkind_mustEscape (s->exitCode));
190 }
191
192 void usymtab_setMustBreak () 
193   /*@modifies utab@*/
194 {
195   llassert (utab != GLOBAL_ENV);
196   utab->mustBreak = TRUE;
197 }
198
199 void usymtab_setExitCode (exitkind ex) 
200    /*@modifies utab@*/
201 {
202   llassert (utab != GLOBAL_ENV);
203
204   utab->exitCode = ex;
205   
206   if (exitkind_mustEscape (ex))
207     {
208       utab->mustBreak = TRUE;
209     }
210 }
211
212 bool usymtab_isAltProbablyDeepNull (sRef s)
213 {
214   return (sRef_deepPred (usymtab_isProbableNullAltBranch, s));
215 }
216
217 static bool usymtab_isProbableNullAltBranch (sRef s) 
218    /*@globals utab@*/
219 {
220   guardSet t;
221   bool res;
222
223   t = utab->guards;
224
225   llassert (utab->env != NULL);
226
227   /*@-mods@*/ /* These modifications are cancelled. */
228   utab->guards = utab->env->guards;
229   utab->env->guards = t;
230   /*@=mods@*/
231
232   llassert (usymtab_isDefined (utab));
233   res = usymtab_isProbableNull (s);
234
235   /*
236   ** This reports a spurious error.  It is okay, because of
237   ** the nesting relationship of usymtab environments.
238   */
239
240   /*@-mods@*/ /* Cancelling modifications. */
241   /*@i1@*/ utab->env->guards = utab->guards;
242   /*@i1@*/ utab->guards = t;
243   /*@=mods@*/ 
244
245   return res;
246 }
247
248 static /*@notnull@*/ /*@special@*/ usymtab
249   usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
250   /*@defines result@*/
251   /*@post:isnull result->htable, result->guards, result->aliases@*/
252 {
253   usymtab t = (usymtab) dmalloc (sizeof (*t));
254   
255   t->nentries = 0;
256   t->nspace = CBASESIZE;
257   t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
258   t->reftable = (nextlevel 
259                  ? NULL
260                  : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
261   
262   t->kind = kind;
263   t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0); 
264
265   t->env = env;
266   t->htable = NULL;
267
268   t->guards = guardSet_undefined;
269   t->aliases = aliasTable_undefined;
270
271     t->mustBreak = FALSE;
272   t->exitCode = XK_NEVERESCAPE;
273
274   return t;
275 }
276
277 /*
278 ** constructors
279 */
280
281 static /*@only@*/ /*@notnull@*/ usymtab
282   usymtab_createRoot (void) /*@modifies nothing@*/
283 {
284   usymtab u = (usymtab) dmalloc (sizeof (*u));
285   
286   u->nentries = 0;
287   u->nspace = CGLOBBASESIZE;
288   u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
289   u->env = GLOBAL_ENV;
290   u->lexlevel = 0;
291   u->htable = hashTable_create (CGLOBHASHSIZE);
292   u->reftable = NULL;
293
294   u->guards = guardSet_new ();
295   u->aliases = aliasTable_new ();
296
297   u->mustBreak = FALSE;
298   u->exitCode = XK_NEVERESCAPE;
299   u->kind = US_NORMAL;
300
301   /*@i23@*/ return (u);
302 }
303
304 void
305 usymtab_initMod (void)
306    /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
307    /*@modifies utab, globtab, filetab, oldtab @*/
308 {
309   utab = usymtab_createRoot ();
310   globtab = utab;
311   filetab = usymtab_undefined;
312   oldtab = usymtab_undefined;
313 }
314
315 /*
316 ** utab should be empty?  (requires?)
317 **
318 ** Adds bool types to symbol table (these are built in for now)
319 ** Only do this is there is no library!
320 */
321
322 void
323 usymtab_initBool ()
324 {
325   if (context_getFlag (FLG_NOLIB))
326     {
327       ctype boolt = ctype_bool;
328       /* evs 2000-07-24: bool is now treated as abstract (always) */
329
330       uentry boolentry = uentry_makeBoolDatatype (YES);
331       usymtab_supGlobalEntry (boolentry);
332       context_addBoolAccess ();
333
334       /*
335       ** We supply values 0 and 1 for the constants, so things like
336       ** while (TRUE) can be interpreted correctly.
337       */
338
339       usymtab_supGlobalEntry 
340         (uentry_makeConstantAux (context_getFalseName (), boolt, 
341                                  fileloc_getBuiltin (), FALSE,
342                                  multiVal_makeInt (0)));
343       usymtab_supGlobalEntry 
344         (uentry_makeConstantAux (context_getTrueName (), boolt, 
345                                  fileloc_getBuiltin (), FALSE,
346                                  multiVal_makeInt (1)));
347     }
348 }
349
350 /*
351 ** mutators 
352 */
353
354 static void
355 usymtab_grow (/*@notnull@*/ usymtab s)
356 {
357   int i;
358   o_uentry *oldsyms = s->entries;
359
360   s->nspace = CBASESIZE;
361   s->entries = (uentry *) dmalloc (sizeof (*s->entries) 
362                                    * (s->nentries + s->nspace));
363
364   for (i = 0; i < s->nentries; i++)
365     {
366       s->entries[i] = oldsyms[i];
367     }
368
369   sfree (oldsyms);
370
371   if (s->reftable != NULL)
372     {
373       refTable oldRefs = s->reftable;
374
375       s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
376                                           * (s->nentries + CBASESIZE + 1));
377       
378       for (i = 0; i < s->nentries; i++)
379         {
380           s->reftable[i] = oldRefs[i];
381         }
382
383       /*@-compdestroy@*/ 
384       sfree (oldRefs);
385       /*@=compdestroy@*/ 
386     }
387       
388 }
389
390 static void
391 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
392 {
393   if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
394     {
395       if (uentry_isDatatype (e) 
396           || uentry_isFunction (e)
397           || uentry_isAnyTag (e)
398           || uentry_isEnumConstant (e)
399           || context_inMacro ())
400         {
401           /* 
402           ** Not a bug.  Code like,
403           **    int f (void) { typedef int tint; ... }
404           ** is legal.
405           */
406           
407           /* was nothing here! */
408           /*@i@*/ e->sref = sRef_saveCopy (e->sref);
409         }
410       else
411         {
412           llparseerror 
413             (cstring_makeLiteral ("Declaration outside function scope"));
414
415           llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
416                               "(lexlevel = %d, modFunction = %s) adding: %q", 
417                               s->lexlevel, bool_unparse (sRef_modInFunction ()), 
418                               uentry_unparse (e)));
419           sRef_setGlobalScope ();
420           /* make sure the sRef is not bashed! */
421           /*@i@*/ e->sref = sRef_saveCopy (e->sref);
422         }
423     }
424
425   if (s->nspace <= 0)
426     {
427       usymtab_grow (s);
428     }
429   
430   s->nspace--;
431   s->entries[s->nentries] = e;
432
433 # ifdef DOANNOTS
434   if (s == globtab || s == filetab)
435     {
436       if (!fileloc_isLib (g_currentloc))
437         {
438           uentry_tallyAnnots (e, AN_UNKNOWN);
439         }
440     }
441 # endif
442
443   if (s->htable != NULL)
444     {
445       hashTable_insert (s->htable, uentry_rawName (e), s->nentries);
446     }
447
448   s->nentries++;
449 }
450
451 static /*@observer@*/ uentry /*@alt void@*/
452 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
453 {
454   /* 
455   ** In theory, we shouldn't need this test because it this is
456   ** only called when a library is being read, and it shouldn't
457   ** ever have a duplicate entry.  In practice, its safer to
458   ** leave it in, though.
459   */
460
461   uentry old;
462
463   if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
464     {
465       DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
466       uentry_free (e); /* duplicate */
467       return old;
468     }
469   else
470     {
471       int thisentry = s->nentries;  
472       
473       if (uentry_isVar (e))
474         {
475           uentry_setSref (e, sRef_makeCvar (globScope, thisentry, 
476                                             uentry_getType (e)));
477         }
478       
479       usymtab_addEntryQuiet (s, e);
480       return e;
481     }
482 }
483
484 static usymId
485 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
486      /*@globals globtab@*/
487      /*@modifies st, e@*/
488 {
489   usymId thisentry = st->nentries;
490
491   llassert (!uentry_isElipsisMarker (e));
492
493   /*
494   ** not true for tags
495   **  llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
496   **/
497
498   llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE, 
499                  ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
500
501   if (st->lexlevel == fileScope 
502       && (!(uentry_isStatic (e)) || uentry_isAnyTag (e))) 
503     {
504       st = globtab;
505     }
506
507   if (isSref)
508     {
509       ctype ct = uentry_getType (e);
510
511       if (uentry_isFunction (e) && ctype_isFunction (ct))
512         {
513           ct = ctype_returnValue (ct);
514         }
515
516       if (uentry_isStatic (e))
517         {
518           sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct);
519
520           if (sRef_isStack (sr) || sRef_isLocalState (sr))
521             {
522               sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
523               sRef_setDefined (sr, uentry_whereLast (e));
524             }
525           
526           uentry_setSref (e, sr);
527         }
528       else
529         {
530           uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct));
531         }
532
533           }
534
535   if (uentry_isDatatype (e))
536     {
537       
538       uentry_setDatatype (e, thisentry);
539     }
540
541   if (uentry_isFunction (e))
542     {
543       ctype ct = uentry_getType (e);
544
545       if (ctype_isFunction (ct)
546           && uentryList_isMissingParams (ctype_argsFunction (ct)))
547         {
548           if (uentry_isDeclared (e))
549             {
550               voptgenerror 
551                 (FLG_NOPARAMS,
552                  message ("Function %q declared without parameter list",
553                           uentry_getName (e)),
554                  uentry_whereDeclared (e));
555             }
556           else
557             {
558               voptgenerror
559                 (FLG_NOPARAMS,
560                  message ("Function %q specified without parameter list",
561                           uentry_getName (e)),
562                  uentry_whereSpecified (e));
563             }
564         }
565     }
566
567   if (st == globtab && !uentry_isSpecified (e))
568     {
569       exprChecks_checkExport (e);
570     }
571   
572   
573   uentry_checkName (e);
574   
575   usymtab_addEntryQuiet (st, e);
576   return (thisentry);
577 }
578
579 usymId
580 usymtab_addEntry (uentry e) 
581    /*@globals utab, globtab@*/
582    /*@modifies utab, e@*/
583 {
584   
585   llassertprint (!usymtab_exists (uentry_rawName (e)),
586                  ("Entry already exists: %s", uentry_unparse (e)));
587
588   return usymtab_addEntryAux (utab, e, FALSE);
589 }
590
591 void
592 usymtab_addGlobalEntry (uentry e)
593    /*@modifies globtab, e@*/ 
594 {
595   DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
596
597   (void) usymtab_addEntryAux (globtab, e, FALSE);
598 }
599
600 /*
601 ** supercede and replace entry use elements of entries array, and
602 ** assign an element to a new value, and then free the old value.
603 ** Need -deparrays to avoid errors for this. 
604 */
605
606 /*@-deparrays@*/ 
607
608 static usymId
609 usymtab_supEntryAux (/*@notnull@*/ usymtab st, 
610                      /*@only@*/ uentry e, bool isSref)
611    /*@globals globtab, filetab@*/
612    /*@modifies st, globtab, e@*/
613 {
614   cstring ename = uentry_rawName (e);
615   bool staticEntry = FALSE;
616   int eindex;
617
618   /* static tags in global scope */
619   if (st->lexlevel == fileScope 
620       && (!(uentry_isStatic (e)) || uentry_isAnyTag (e))) 
621     {
622       eindex = usymtab_getIndex (st, ename);
623
624       if (eindex != NOT_FOUND)
625         {
626           uentry ce = st->entries[eindex];      
627           
628           if (optgenerror
629               (FLG_SHADOW,
630                message ("%s %q shadows static declaration",
631                         ekind_capName (uentry_getKind (e)),
632                         uentry_getName (e)),
633                uentry_whereDeclared (e)))
634             {
635               uentry_showWhereLast (ce);
636             }
637
638           if (eindex == st->nentries - 1)
639             {
640              ;
641             }
642           else
643             {
644               st->entries[eindex] = st->entries[st->nentries - 1];
645             }
646
647           if (st->htable != NULL)
648             {
649               hashTable_replaceKey (st->htable, uentry_rawName (ce), 
650                                     uentry_rawName (e));
651             }
652
653           uentry_free (ce);
654           st->nentries--;
655         }
656       
657       st = globtab;
658     }
659
660   if (uentry_isStatic (e)) {
661     if (uentry_isFunction (e)) {
662       /* Static function declarations are at the file level, even if they are in a deeped scope. */
663       st = usymtab_getFileTab ();
664       staticEntry = TRUE;
665     } else {
666       if (!uentry_isAnyTag (e) && st == globtab) 
667         {
668           st = usymtab_getFileTab ();
669           staticEntry = TRUE;
670           DPRINTF (("Static entry!"));
671         }
672     }
673   }
674
675   DPRINTF (("Using symtab: %s", usymtab_unparseLocalAux (st)));
676
677   eindex = usymtab_getIndex (st, ename);
678       
679   if (eindex != NOT_FOUND)
680     {
681       uentry ce = st->entries[eindex];
682
683       DPRINTF (("Found entry: %s", uentry_unparse (ce)));
684
685       if (uentry_isPriv (ce)
686           /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
687           || (uentry_isStatic (ce) 
688               && uentry_isAnyTag (ce)
689               && (uentry_isDeclared (ce) 
690                   && !fileloc_sameFile (uentry_whereDefined (ce),
691                                         uentry_whereDefined (e)))))
692         {
693           /*
694           ** overload entry 
695           **    if overloading import should do some checks!
696           */
697
698           llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
699           
700           st->entries[eindex] = e;
701
702           if (uentry_isDatatype (e))
703             {
704               uentry_setDatatype (e, eindex);
705             }
706           
707           if (st == globtab && !uentry_isSpecified (e))
708             {
709               exprChecks_checkExport (e);
710             }
711
712           if (st->htable != NULL)
713             {
714               hashTable_replaceKey (st->htable, uentry_rawName (ce), 
715                                     uentry_rawName (e));
716             }
717
718           uentry_free (ce);
719           ce = e; 
720         }
721       else if (uentry_isSpecified (ce))
722         {
723           if (uentry_isSpecified (e))
724             {
725               if (fileloc_isImport (uentry_whereSpecified (ce)))
726                 {
727                   
728                   if (st->htable != NULL)
729                     {
730                       hashTable_replaceKey (st->htable, 
731                                             uentry_rawName (ce), 
732                                             uentry_rawName (e));
733                     }
734                   
735                   uentry_free (ce); 
736                   st->entries[eindex] = e;
737                   ce = e;
738
739                   if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
740                 }
741               else 
742                 {
743                   if (fileloc_isImport (uentry_whereSpecified (e)))
744                     {
745                       uentry_free (e);
746                     }
747                   else
748                     {
749                       /* respecification errors already reported */
750   
751                       if (uentry_isDatatype (e)) 
752                         {
753                           uentry_setDatatype (e, eindex);
754                         }
755                       
756                       if (st->htable != NULL)
757                         {
758                           hashTable_replaceKey (st->htable, 
759                                                 uentry_rawName (ce), 
760                                                 uentry_rawName (e));
761                         }
762                       
763                       llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
764                       uentry_free (ce);
765                       st->entries[eindex] = e;
766                       ce = e;
767                     } 
768                 }
769             }
770           else /* e not specified */
771             {
772               if (uentry_isDeclared (ce))
773                 {
774                   llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
775                   uentry_mergeDefinition (ce, e);
776                 }
777               else 
778                 {
779                   llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
780                   uentry_mergeEntries (ce, e);
781                 }
782             }
783         }
784       else /* ce not specified */
785         {
786           if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
787             {
788               if (uentry_isDatatype (e) || uentry_isAnyTag (e)
789                   || uentry_isEnumConstant (e))
790                 {
791                   ; /* 
792                      ** Not a bug.  Code like,
793                      **    int f (void) { typedef int tint; ... }
794                      ** is legal.
795                      */
796                 }
797               else
798                 {
799                   llcontbug (message ("usymtab_supEntryAux: inconsistent state "
800                                       "(lexlevel = %d, modFunction = %s) adding: %q", 
801                                       st->lexlevel, bool_unparse (sRef_modInFunction ()), 
802                                       uentry_unparse (e)));
803
804                   if (sRef_modInFunction ())
805                     {
806                       /* make sure the sRef is not bashed! */
807                       /*@i@*/ e->sref = sRef_saveCopy (e->sref);
808                     }
809                 }
810             }
811           
812           uentry_mergeDefinition (ce, e);
813         }
814       
815       if (isSref)
816         {
817           ctype ct = uentry_getType (ce);
818           
819           if (uentry_isFunction (ce) && ctype_isFunction (ct))
820             {
821               ct = ctype_returnValue (ct);
822             }
823           
824           uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct));
825                 }
826     }
827   else /* no previous entry */
828     {
829       uentry outer;
830
831       if (st->lexlevel == globScope 
832           && !uentry_isStatic (e)
833           && !uentry_isExtern (e)
834           && usymtab_isDefined (filetab))
835         {
836           /*
837           ** check if there is a static entry:  (i.e.,
838           **   
839           **    static int f ();
840           **    ...
841           **    int f (); 
842           */
843           
844           eindex = usymtab_getIndex (filetab, ename);
845           
846           if (eindex != NOT_FOUND)
847             {
848               uentry ce = filetab->entries[eindex];
849
850               uentry_setStatic (e);
851               uentry_mergeDefinition (ce, e);
852               staticEntry = TRUE;
853               goto exitPoint;
854             }
855         }
856       
857       outer = usymtab_lookupQuiet (st->env, ename);
858
859       /*
860       ** no previous definition, add the new one
861       */
862       
863       if (!noshadowerror 
864           && uentry_isValid (outer)
865           && !(uentry_isYield (e) || uentry_isYield (outer))
866           && fileloc_isDefined (uentry_whereLast (e))
867           && fileloc_isDefined (uentry_whereLast (outer)))
868         {
869           if (!uentry_sameKind (outer, e))
870             {
871               ; /* no error */
872             }
873           else
874             {
875               if (ctype_isUnknown (uentry_getType (outer))
876                   || uentry_isForward (outer))
877                 {
878                   ;
879                 }
880               else
881                 {
882                   if (optgenerror 
883                       (FLG_SHADOW,
884                        message ("%s %q shadows outer declaration",
885                                 ekind_capName (uentry_getKind (e)),
886                                 uentry_getName (e)),
887                        uentry_whereLast (e)))
888                     {
889                       uentry_showWhereLast (outer);
890                     }
891                 }
892             }
893         }
894       
895       if (st == globtab && context_getFlag (FLG_NEWDECL))
896         {
897           voptgenerror 
898             (FLG_NEWDECL,
899              message ("New declaration: %q", uentry_getName (e)),
900              uentry_whereLast (e));
901         }
902
903       eindex = usymtab_addEntryAux (st, e, isSref);
904     }
905
906  exitPoint:
907     return (staticEntry ? USYMIDINVALID : eindex);
908 }
909
910 # ifndef NOLCL
911 static void
912 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
913    /*@globals globtab@*/ /*@modifies st, e@*/
914 {
915   cstring ename = uentry_rawName (e);
916   int eindex;
917
918   /* static tags in global scope */
919   eindex = usymtab_getIndex (st, ename);
920   
921   if (eindex != NOT_FOUND)
922     {
923       uentry ce = st->entries[eindex];      
924       
925       if (st->htable != NULL)
926         {
927           hashTable_replaceKey (st->htable, uentry_rawName (ce), uentry_rawName (e));
928         }
929
930       uentry_free (ce);
931       st->entries[eindex] = e;
932     }
933   else
934     {
935       eindex = usymtab_addEntryAux (st, e, FALSE);
936     }
937 }
938 # endif
939
940 /*@=deparrays@*/ 
941
942 void usymtab_supEntry (uentry e)
943    /*@globals utab, filetab, globtab@*/
944    /*@modifies utab, globtab, e@*/
945 {
946     (void) usymtab_supEntryAux (utab, e, FALSE);
947 }
948
949 /*
950 ** this should be lots more efficient!
951 */
952
953 static /*@exposed@*/ uentry 
954   usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab, 
955                              /*@only@*/ uentry e, bool isref)
956   /*@globals globtab, filetab@*/
957   /*@modifies tab, globtab, e@*/
958 {
959   cstring rawName = cstring_copy (uentry_rawName (e));
960   bool stat = (tab == globtab) && uentry_isStatic (e);
961   uentry ret;
962
963     
964   (void) usymtab_supEntryAux (tab, e, isref);
965
966   if (stat)
967     {
968       ret = usymtab_lookupAux (filetab, rawName);
969     }
970   else
971     {
972       ret = usymtab_lookupAux (tab, rawName);
973
974       if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
975         {
976           ret = usymtab_lookupAux (filetab, rawName);
977         }
978     }
979   
980   cstring_free (rawName);
981   return ret;
982 }
983
984 /*@dependent@*/ /*@exposed@*/ uentry 
985   usymtab_supEntryReturn (/*@only@*/ uentry e)
986   /*@globals utab, filetab, globtab@*/
987   /*@modifies utab, globtab, e@*/
988 {
989   return (usymtab_supEntryReturnAux (utab, e, FALSE));
990 }
991
992 /*@dependent@*/ /*@exposed@*/ uentry 
993   usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
994   /*@globals utab, globtab, filetab@*/
995   /*@modifies utab, globtab, e@*/
996 {
997   return (usymtab_supEntryReturnAux (utab, e, TRUE));
998 }
999
1000 /*@dependent@*/ /*@exposed@*/ uentry 
1001   usymtab_supGlobalEntryReturn (uentry e)
1002   /*@globals globtab, filetab@*/
1003   /*@modifies globtab, e@*/
1004 {
1005   uentry ret;
1006
1007   ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1008
1009   if (sRef_modInFunction ())
1010     {
1011       recordFunctionType (ret);
1012     }
1013
1014   return (ret);
1015 }
1016
1017 ctype
1018 usymtab_supTypeEntry (/*@only@*/ uentry e)
1019   /*@globals globtab, filetab@*/
1020   /*@modifies globtab, e@*/
1021 {
1022   usymId uid;
1023   ctype ret;
1024
1025   if (uentry_isAbstractDatatype (e))
1026     {
1027       uid = usymtab_supAbstractTypeEntry (e, FALSE);
1028       ret = ctype_createAbstract (uid);
1029     }
1030   else
1031     {
1032       uid = usymtab_supEntryAux (globtab, e, FALSE);
1033       ret = ctype_createUser (uid);
1034     }
1035
1036   if (sRef_modInFunction ())
1037     {
1038       recordFunctionType (globtab->entries[uid]);
1039     }
1040
1041   return ret;
1042 }
1043
1044 uentry
1045 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1046   /*@globals globtab, filetab@*/
1047   /*@modifies globtab@*/
1048 {
1049   usymId uid;
1050   
1051   if (uentry_isAbstractDatatype (e))
1052     {
1053       uid = usymtab_supAbstractTypeEntry (e, FALSE);
1054     }
1055   else
1056     {
1057       uid = usymtab_supEntryAux (globtab, e, FALSE);
1058     }
1059   
1060   if (sRef_modInFunction ())
1061     {
1062       recordFunctionType (globtab->entries[uid]);
1063     }
1064
1065     return (globtab->entries[uid]);
1066 }
1067
1068 usymId
1069 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1070   /*@globals globtab, filetab@*/
1071   /*@modifies globtab, e@*/
1072 {
1073   usymId uid;
1074   uid = usymtab_supEntryAux (globtab, e, FALSE);
1075
1076   if (dodef)
1077     {
1078       uentry ue = usymtab_getTypeEntry (uid);
1079       uentry_setDatatype (ue, uid);
1080     }
1081
1082   if (context_getFlag (FLG_ACCESSMODULE))
1083     {
1084       context_addFileAccessType (uid);
1085     }
1086
1087   if (sRef_modInFunction ())
1088     {
1089       recordFunctionType (globtab->entries[uid]);
1090     }
1091
1092   return (uid);
1093 }
1094
1095 # ifndef NOLCL
1096 usymId
1097 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1098   /*@globals globtab, filetab@*/
1099   /*@modifies globtab, e@*/
1100 {
1101   usymId uid;
1102
1103   uid = usymtab_supEntryAux (globtab, e, FALSE);
1104
1105   if (dodef)
1106     {
1107       uentry ue = usymtab_getTypeEntry (uid);
1108
1109       uentry_setDatatype (ue, uid);
1110     }
1111
1112   if (sRef_modInFunction ())
1113     {
1114       recordFunctionType (globtab->entries[uid]);
1115     }
1116
1117   return (uid);
1118 }
1119 # endif
1120
1121 ctype
1122 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1123   /*@globals globtab, filetab@*/
1124   /*@modifies globtab, e@*/
1125 {
1126   usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1127   uentry ue = usymtab_getTypeEntry (uid);
1128
1129     uentry_setDatatype (ue, uid);
1130
1131   if (sRef_modInFunction ())
1132     {
1133       recordFunctionType (globtab->entries[uid]);
1134     }
1135
1136   return (uentry_getAbstractType (ue));
1137 }
1138
1139 void
1140   usymtab_supEntrySref (uentry e)
1141   /*@globals utab, globtab, filetab@*/
1142   /*@modifies utab, globtab, e@*/
1143 {
1144   sRef old = uentry_getSref (e);
1145
1146   
1147   if (sRef_isType (old))
1148     {
1149       uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1150
1151       /*@access uentry@*/
1152       if (uentry_isValid (ue)) 
1153         {
1154           sRef uref = uentry_getSref (ue);
1155
1156           sRef_mergeStateQuiet (uref, old); 
1157           sRef_clearDerived (uref);
1158         }
1159       /*@noaccess uentry@*/
1160     }
1161   else if (sRef_isKnown (old))
1162     {
1163       usymtab_supEntry (e);
1164     }
1165   else
1166     {
1167       (void) usymtab_supEntryAux (utab, e, TRUE);
1168     }
1169 }
1170
1171 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1172   /*@globals globtab, filetab@*/
1173   /*@modifies globtab, filetab, e@*/
1174 {
1175   usymId uid;
1176
1177   DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1178
1179   uid = usymtab_supEntryAux (globtab, e, FALSE);
1180
1181   if (sRef_modInFunction ())
1182     {
1183       recordFunctionType (globtab->entries[uid]);
1184     }
1185 }
1186
1187 uentry
1188   usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1189   /*@globals filetab, globtab@*/
1190   /*@modifies filetab, globtab, e@*/
1191 {
1192   llassert (filetab != usymtab_undefined);
1193   DPRINTF (("File entry: %s", uentry_unparse (e)));
1194   return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1195 }
1196
1197 /*
1198 ** observers
1199 */
1200
1201 bool
1202 usymtab_inDeepScope () /*@globals utab@*/
1203 {
1204   return (utab->lexlevel > paramsScope);
1205 }
1206
1207 static int
1208 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1209 {
1210   int i;
1211
1212   if (s->htable != NULL)
1213     {
1214       i = hashTable_lookup (s->htable, k);
1215
1216       return i;
1217     }
1218   else
1219     {
1220       for (i = 0; i < s->nentries; i++)
1221         {
1222           uentry current = s->entries[i];
1223
1224           if (!uentry_isUndefined (current) 
1225               && cstring_equal (uentry_rawName (current), k))
1226             {
1227               return i;
1228             }
1229         }
1230
1231       return NOT_FOUND;
1232     }
1233 }
1234
1235 static uentry
1236 usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1237 {
1238   llassert (i >= 0 && i < s->nentries);
1239   return (s->entries[i]);
1240 }
1241
1242 usymId
1243 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1244 {
1245   usymId uid = usymtab_getIndex (globtab, k);
1246
1247   if (uid == NOT_FOUND) return USYMIDINVALID;
1248
1249   if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
1250     return USYMIDINVALID;
1251   }
1252
1253   return uid;
1254 }
1255
1256 /*@dependent@*/ uentry
1257 usymtab_lookupStructTag (cstring k)
1258 {
1259   cstring sname = makeStruct (k);
1260   uentry ue = usymtab_lookupGlob (sname);
1261     cstring_free (sname);
1262   return (ue);
1263 }
1264
1265 /*@dependent@*/ uentry
1266 usymtab_lookupUnionTag (cstring k)
1267 {
1268   cstring uname = makeUnion (k);
1269   uentry res = usymtab_lookupGlob (uname);
1270
1271   cstring_free (uname);
1272   return res;
1273 }
1274
1275 /*@dependent@*/ uentry
1276 usymtab_lookupEnumTag (cstring k)
1277 {
1278   cstring ename = makeEnum (k);
1279   uentry res = usymtab_lookupGlob (ename);
1280
1281   cstring_free (ename);
1282   return res;
1283 }
1284
1285 usymId
1286 usymtab_getId (cstring k) /*@globals globtab@*/
1287 {
1288   usymId uid = usymtab_getIndex (globtab, k);
1289   uentry ue;
1290
1291   if (uid == NOT_FOUND)
1292     {
1293       return USYMIDINVALID;
1294     }
1295
1296   ue = usymtab_getGlobalEntry (uid);
1297
1298   if (uentry_isPriv (ue))
1299     {
1300       return USYMIDINVALID;
1301     }
1302
1303   return uid;
1304 }
1305
1306 static /*@exposed@*/ uentry 
1307 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1308 {
1309   llassert (uid != USYMIDINVALID);
1310  
1311   if (uid < 0 || uid >= s->nentries)
1312     {
1313       llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1314                           s->lexlevel, uid));
1315       return uentry_undefined;
1316     }
1317
1318   llassertprint (uentry_isValid (s->entries[uid]),
1319                  ("entry undefined: %d", uid));
1320
1321   return s->entries[uid];
1322 }
1323
1324 /*@dependent@*/ /*@observer@*/ uentry 
1325   usymtab_getGlobalEntry (usymId uid)
1326   /*@globals utab, globtab@*/
1327 {
1328   if (dbgfree) return (uentry_undefined);
1329   
1330   if (utab->lexlevel > paramsScope)
1331     {
1332       /* need to do this the awkward way, since it could be in conditional scope */
1333      return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1334     }
1335   else
1336     {
1337       return (globtab->entries[uid]);
1338     }
1339 }
1340
1341 /*@dependent@*/ /*@exposed@*/ uentry 
1342   usymtab_getTypeEntry (usymId uid)
1343   /*@globals globtab@*/
1344 {
1345   if (dbgload)
1346     {
1347       if (uid >= 0 && uid < globtab->nentries)
1348         {
1349           return (globtab->entries[uid]);
1350         }
1351       else
1352         {
1353           return (uentry_undefined);
1354         }
1355     }
1356   else
1357     {
1358       llassert (uid >= 0 && uid < globtab->nentries);
1359       
1360       return (globtab->entries[uid]);
1361     }
1362 }
1363
1364 /*
1365 ** in load files
1366 */
1367
1368 /*@dependent@*/ /*@exposed@*/ uentry 
1369   usymtab_getTypeEntrySafe (usymId uid)
1370   /*@globals globtab@*/
1371 {
1372   if (uid < 0 || uid >= globtab->nentries)
1373     {
1374       return uentry_undefined;
1375     }
1376
1377       return (globtab->entries[uid]);
1378 }
1379
1380 bool
1381   usymtab_isBoolType (usymId uid)
1382   /*@globals globtab@*/
1383 {
1384   llassert (uid >= 0 && uid < globtab->nentries);
1385
1386   return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1387                          context_getBoolName ()));
1388 }
1389  
1390 cstring
1391 usymtab_getTypeEntryName (usymId uid)
1392    /*@globals globtab@*/
1393 {
1394   uentry ue;
1395
1396   if (dbgfree)
1397     {
1398       return (cstring_makeLiteral ("<freetype>"));
1399     }
1400
1401   ue = usymtab_getTypeEntry (uid);
1402
1403   if (dbgload && !uentry_isValid (ue))
1404     {
1405       return (message ("<missing type: %d>", uid));
1406     }
1407
1408   llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1409
1410   return (uentry_getName (ue));
1411 }
1412
1413 static void
1414 usymtab_rehash (/*@notnull@*/ usymtab s)
1415 {
1416   int i;
1417   
1418   if (s->htable != NULL)
1419     {
1420       hashTable_free (s->htable);
1421     }
1422   
1423   s->htable = hashTable_create (LLHASHSIZE);
1424
1425   for (i = 0; i < s->nentries; i++)
1426     {
1427       hashTable_insert (s->htable, uentry_rawName (s->entries[i]), i);
1428     }
1429 }
1430
1431 /*
1432 ** superficial copy of usymtab
1433 **
1434 ** DO copy spec entries 
1435 */
1436
1437 static /*@only@*/ /*@notnull@*/ usymtab
1438 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1439 {
1440   usymtab copytab = usymtab_createRoot ();
1441   int i;
1442
1443   for (i = 0; i < s->nentries; i++)
1444     {
1445       usymtab_addEntryBase (copytab, s->entries[i]);
1446     }
1447
1448   return copytab;
1449 }
1450
1451 static void
1452 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1453 {
1454   aliasTable_free (s->aliases);
1455   refTable_free (s->reftable, s->nentries);
1456   sfree (s->entries);
1457   /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1458 }
1459
1460 /*
1461 ** converts usymId from old table to sorted one
1462 */
1463
1464 usymId 
1465   usymtab_convertId (usymId uid)
1466   /*@globals oldtab, utab@*/
1467 {
1468   uentry ue;
1469   usymId ret;
1470   cstring name;
1471
1472   llassert (usymtab_isDefined (oldtab));
1473
1474   ue = usymtab_getEntryAux (oldtab, uid);
1475
1476   llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1477
1478   name = uentry_rawName (ue);
1479
1480   ret = usymtab_getIndex (utab, name);
1481
1482   llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1483
1484   return (ret);
1485 }
1486
1487 void
1488 usymtab_prepareDump (void)
1489    /*@globals oldtab, utab@*/
1490    /*@modifies oldtab, utab@*/
1491 {
1492   llassert (usymtab_inGlobalScope ());
1493
1494   llassert (oldtab == usymtab_undefined);
1495
1496   oldtab = usymtab_shallowCopy (utab);
1497
1498   /* 
1499      alpha compare - make sure order is same on different platforms
1500      error messages appear in same order 
1501   */
1502
1503   qsort (utab->entries, (size_t)utab->nentries, 
1504          sizeof (*utab->entries), (int (*)(const void *, const void *)) uentry_xcomparealpha);
1505
1506   usymtab_rehash (utab);
1507 }
1508
1509 void
1510   usymtab_dump (FILE *fout)
1511   /*@globals utab, oldtab@*/
1512 {
1513   int i;
1514   bool neednl = FALSE;
1515   uentry lastentry = uentry_undefined;
1516   ekind lastekind = KINVALID;
1517   int linelen = 0;
1518
1519   /*
1520   ** must call prepareDump first
1521   */
1522
1523   llassert (oldtab != usymtab_undefined);
1524
1525   for (i = 0; i < utab->nentries; i++)
1526     {
1527       uentry thisentry = utab->entries[i];
1528       ekind  thisekind = uentry_getKind (thisentry);
1529
1530       
1531       if (uentry_hasRealName (thisentry)) {
1532         if (thisekind != lastekind)
1533           {
1534             if (neednl)
1535               {
1536                 check (fputc ('\n', fout) == (int) '\n');
1537               }
1538             
1539             neednl = FALSE;
1540             lastentry = uentry_undefined;
1541             fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),  
1542                      cstring_toCharsSafe (ekind_capName (thisekind)));
1543             lastekind = thisekind;
1544             linelen = 0;
1545           }
1546         
1547         if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1548             || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH))))
1549           {
1550             cstring cdump = uentry_dump (thisentry);
1551             
1552             lastentry = thisentry;
1553             if (neednl)
1554               {
1555                 check (fputc ('\n', fout) == (int) '\n');
1556                 linelen = 0;
1557               }
1558             
1559             linelen += cstring_length (cdump);
1560             
1561             /* no new line here! */
1562             if (cstring_length (cdump) > 0) 
1563               {
1564                 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1565               }
1566             
1567             cstring_free (cdump);
1568             neednl = TRUE;
1569           }
1570         else
1571           {
1572             cstring cdump = uentry_rawName (thisentry);
1573                     linelen += cstring_length (cdump);
1574             fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1575           }
1576       }
1577     }
1578
1579   if (neednl)
1580     {
1581       check (fputc ('\n', fout) == (int) '\n');
1582     }
1583 }
1584
1585 void usymtab_load (FILE *f)
1586   /*@globals utab, globtab@*/
1587   /*@modifies utab, *f@*/
1588 {
1589   char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1590   char *os = s;
1591   ekind kind = KINVALID;
1592   fileloc loc = g_currentloc;
1593   char c;
1594   uentry ue;
1595
1596   dbgload = TRUE;
1597
1598   llassert (utab == globtab);
1599   llassert (utab->nentries == 0);
1600
1601   while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL 
1602          && *s == ';')
1603     {
1604       ; /* ignore ;-comments */
1605     }
1606
1607   while (s != NULL && *s != ';')
1608     {
1609       
1610       if (*s == '*')
1611         {
1612           s++;
1613           kind = ekind_fromInt (getInt (&s));
1614
1615                   goto nextiter;
1616         }
1617
1618       if (*s == '$')
1619         {
1620           llfatalerror
1621             (cstring_makeLiteral 
1622              ("Library is in obsolete format.  Use lclint +whichlib "
1623               "to see which library is being loaded."));
1624         }
1625
1626       ue = uentry_undump (kind, loc, &s);
1627       DPRINTF (("Load: %s", uentry_unparseFull (ue)));
1628
1629       if (uentry_isValid (ue))
1630         {       
1631           ue = usymtab_addEntryBase (utab, ue);
1632           /*@-branchstate@*/ 
1633         } 
1634       /*@=branchstate@*/
1635
1636       /*
1637       ** now, any other names are the same uentry
1638       */
1639
1640       while (*(s++) == '#')
1641         {
1642           cstring name = cstring_fromCharsO (getWord (&s));
1643           uentry nue = uentry_nameCopy (name, ue);
1644
1645           DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1646           usymtab_addEntryBase (utab, nue);
1647         }
1648
1649       while ((c = *s) != '\0' && (c !='\n'))
1650         {
1651           if (c != ' ' || c != '\t') 
1652             {
1653               llbuglit ("Junk in load file");
1654             }
1655
1656           s++;
1657         }
1658
1659     nextiter:
1660       s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1661     }
1662
1663   dbgload = FALSE;
1664   sfree (os);
1665 }
1666
1667 /*
1668 ** file scope for static variables
1669 */
1670
1671 void
1672 usymtab_enterFile ()
1673   /*@globals utab, globtab, filetab@*/
1674   /*@modifies filetab@*/
1675 {
1676   llassert (utab == globtab);
1677
1678   # if 0
1679   /* check globals */
1680   
1681   usymtab_entries (globtab, ue)
1682     {
1683       if (sRef_hasDerived (uentry_getSref (ue)))
1684         {
1685           fprintf (g_msgstream, "Derived Global: %s\n", uentry_unparse (ue));
1686           fprintf (g_msgstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
1687         }
1688     } end_usymtab_entries ;
1689
1690   # endif
1691
1692   usymtab_enterScope ();
1693   filetab = utab;
1694 }
1695
1696 void
1697 usymtab_exitFile ()
1698    /*@globals utab, filetab@*/
1699    /*@modifies filetab, utab@*/
1700 {
1701   
1702   llassert (utab->lexlevel == 1);
1703
1704   usymtab_exitScope (exprNode_undefined);
1705   filetab = NULL;
1706 }
1707
1708 void
1709 usymtab_enterScope ()
1710   /*@globals utab, globtab, filetab@*/
1711   /*@modifies utab@*/
1712 {
1713   usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
1714           
1715   /* unconditional scope: optimize to avoid copy */
1716   t->aliases = aliasTable_copy (utab->aliases); 
1717   utab = t;
1718   
1719   llassert (usymtab_isDefined (t->env));
1720   
1721   if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
1722     {
1723       noshadowerror = TRUE;
1724       usymtab_handleParams ();
1725       noshadowerror = FALSE;
1726     }
1727 }
1728
1729 /*
1730 ** setup external references:
1731 **    o only, unique params alias external args
1732 **    o other params may alias anything of their type
1733 */
1734  
1735 static void
1736 usymtab_handleParams (void)
1737   /*@globals utab, globtab, filetab@*/
1738   /*@modifies utab, globtab@*/
1739 {
1740   usymtab ptab = utab->env;
1741   uentry fcn = context_getHeader ();
1742
1743   
1744   usymtab_entries (ptab, param)
1745     {
1746       uentry ue;
1747
1748       if (!uentry_isYield (param))
1749         {
1750           sRef uref;
1751           sRef pref = uentry_getSref (param);
1752           
1753           llassertprint (uentry_isAnyParam (param), 
1754                          ("not param: %s", 
1755                           uentry_unparseFull (param)));
1756           
1757           
1758           ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
1759                                     uentry_getType (param),
1760                                     fileloc_copy (uentry_whereDeclared (param)),
1761                                     FALSE);
1762
1763           uentry_copyState (ue, param);
1764           uentry_setRefParam (ue);
1765           
1766           ue = usymtab_supEntrySrefReturn (ue);
1767                   
1768           /* must be after supercede! */
1769           
1770           if (!sRef_stateKnown (pref))
1771             {
1772               uentry_setDefState (ue, SS_DEFINED);
1773               uentry_setDefState (param, SS_DEFINED);
1774             }
1775           else
1776             {
1777               if (sRef_isStateSpecial (pref))
1778                 {
1779                   uentry_setDefState (ue, SS_ALLOCATED);
1780                 }
1781               else
1782                 {
1783                   uentry_setDefState (ue, sRef_getDefState (pref));
1784                 }
1785             }
1786
1787           uref = uentry_getSref (ue);
1788           
1789           if (sRef_isStack (uref))
1790             {
1791               alkind pkind = sRef_getAliasKind (pref);
1792
1793               if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
1794                   && !alkind_isStack (pkind))
1795                 {
1796                   sRef_setAliasKind (uref, pkind, fileloc_undefined);
1797                   sRef_setOrigAliasKind (uref, pkind);
1798                 }
1799               else
1800                 {
1801                   sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
1802                   sRef_setOrigAliasKind (uref, AK_IMPTEMP);
1803
1804                   if (uentry_isOut (param))
1805                     {
1806                       ;
1807                     }
1808                   else
1809                     {
1810                       sRef_setDefined (uref, fileloc_undefined);
1811                     }
1812                 }
1813
1814                     }
1815
1816                   usymtab_addMustAlias (uref, pref);   
1817
1818           if (!(uentry_isOnly (param) || uentry_isUnique (param)))
1819             {
1820               sRef s = sRef_makeExternal (uref);
1821
1822                       usymtab_addMustAlias (uref, s);   
1823             }
1824           
1825           if (sRef_isKillRef (pref))
1826             {
1827               sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
1828               sRef_setOrigAliasKind (uref, AK_KILLREF);
1829             }
1830           else if (sRef_isRefCounted (uref))
1831             {
1832               sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
1833             }
1834           else
1835             {
1836               /* was AK_UNIQUE */
1837               sRef_setOrigAliasKind (uref, AK_LOCAL);
1838             }
1839         }
1840       else
1841         {
1842                 }
1843     } end_usymtab_entries;
1844
1845
1846   if (uentry_hasSpecialClauses (fcn))
1847     {
1848       specialClauses clauses = uentry_getSpecialClauses (fcn);
1849
1850       specialClauses_preElements (clauses, cl)
1851         {
1852           sRefSet refs = specialClause_getRefs (cl);
1853           sRefMod modf = specialClause_getEntryFunction (cl);
1854
1855           
1856           sRefSet_elements (refs, el)
1857             {
1858               sRef base = sRef_getRootBase (el);
1859               
1860               if (sRef_isResult (base))
1861                 {
1862                   ; /* nothing to do before */
1863                 }
1864               else if (sRef_isParam (base))
1865                 {
1866                   if (modf != NULL)
1867                     {
1868                       sRef sb = sRef_updateSref (el);
1869                       sRefSet aliases = usymtab_allAliases (sb);
1870                       
1871                                       modf (sb, fileloc_undefined);
1872                                       
1873                       sRefSet_elements (aliases, sr)
1874                         {
1875                                                   modf (sr, fileloc_undefined);
1876                                                 } end_sRefSet_elements ;
1877
1878                       sRefSet_free (aliases);
1879                     }
1880                 }
1881               else
1882                 {
1883                   if (sRef_isValid (base))
1884                     {
1885                       BADBRANCH;
1886                     }
1887                 }
1888             } end_sRefSet_elements ;      
1889         } end_specialClauses_preElements ;
1890     }
1891   }
1892   
1893 void
1894 usymtab_enterFunctionScope (uentry fcn)
1895   /*@globals utab, filetab, globtab@*/
1896   /*@modifies utab@*/
1897 {
1898   usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
1899
1900   if (utab->lexlevel != fileScope)
1901     {
1902       if (utab->lexlevel > fileScope)
1903         {
1904           llparseerror (cstring_makeLiteral ("New function scope inside function."));
1905           
1906           while (utab->lexlevel > fileScope)
1907             {
1908               /*@i@*/ utab = usymtab_dropEnv (utab);
1909               /*@-branchstate@*/
1910             }
1911           /*@=branchstate@*/
1912         }
1913       else
1914         {
1915           llfatalbug (cstring_makeLiteral ("New function not inside file."));
1916         }
1917     /*@-branchstate@*/ } /*@=branchstate@*/
1918
1919   globSet_allElements (uentry_getGlobs (fcn), el)
1920     {
1921       
1922       if (sRef_isUndefGlob (el))
1923         {
1924           int index = sRef_getScopeIndex (el);
1925           sRef sr = sRef_updateSref (el);
1926           fileloc loc = uentry_whereEarliest (fcn);
1927           
1928           if (sRef_isFileStatic (el))
1929             {
1930               ctype ct = sRef_getType (el);
1931               uentry ue;
1932               
1933               llassert (usymtab_isDefined (filetab));
1934
1935               ue = usymtab_fetchIndex (filetab, index);
1936               
1937               if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
1938                 {
1939                   sRef_setAllocated (sr, loc);
1940                 }
1941               else
1942                 {
1943                   sRef_setUndefined (sr, loc);
1944                 }
1945             }
1946           else
1947             {
1948               uentry ue = globtab->entries[index];
1949               ctype ct = uentry_getType (ue);
1950               
1951               if (ctype_isArray (ct) || ctype_isSU (ct))
1952                 {
1953                   sRef_setAllocated (sr, loc);
1954                 }
1955               else
1956                 {
1957                   sRef_setUndefined (sr, loc);
1958                 }
1959             }
1960         }
1961       else if (sRef_isAllocated (el))
1962         {
1963           sRef sr = sRef_updateSref (el);
1964           fileloc loc = uentry_whereEarliest (fcn);
1965           
1966           sRef_setAllocated (sr, loc);
1967         }
1968       else if (sRef_isPartial (el))
1969         {
1970           sRef sr = sRef_updateSref (el);
1971           fileloc loc = uentry_whereEarliest (fcn);
1972
1973           sRef_setPartial (sr, loc);
1974         }
1975       else
1976         {
1977           /* defined */ ;
1978         }
1979     } end_globSet_allElements;
1980
1981   utab = t;
1982 }
1983
1984 static void
1985 usymtab_caseBranch (void)
1986   /*@modifies utab@*/
1987 {
1988   usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
1989   utab = t;
1990 }
1991
1992 void
1993 usymtab_switchBranch (/*@unused@*/ exprNode s)
1994   /*@modifies utab@*/
1995 {
1996   usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
1997
1998   t->aliases = aliasTable_copy (utab->aliases);
1999     utab = t;
2000 }
2001
2002 void
2003 usymtab_trueBranch (/*@only@*/ guardSet guards)
2004   /*@modifies utab@*/
2005 {
2006   usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2007
2008   /*
2009   ** not true! (could be in a macro)
2010   **
2011   ** llassertprint (utab->lexlevel > paramsScope,
2012   ** ("not in scope: %s", usymtab_unparseLocal ()));
2013   **
2014   */
2015
2016   guardSet_free (t->guards);
2017   t->guards = guards;
2018
2019     aliasTable_free (t->aliases);
2020   t->aliases = aliasTable_copy (utab->aliases);
2021   
2022     utab = t;
2023 }
2024
2025 /*
2026 ** consider,
2027 ** 
2028 **   { int a; if (...) a = 3; < a may be undefined here!
2029 **
2030 */
2031
2032 void
2033 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl)
2034 {
2035   /*
2036   ** add a false branch
2037   ** (could be done more efficiently as a special case, but
2038   ** it is better to only maintain one version of the code)
2039   */
2040
2041   usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2042   usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2043 }
2044
2045 void
2046 usymtab_popCaseBranch () /*@modifies utab@*/
2047 {
2048   llassert (utab->kind == US_CBRANCH);
2049   usymtab_quietPlainExitScope ();
2050 }
2051
2052 void
2053 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2054 {
2055   /*
2056   ** add a false branch that must return --- that is,
2057   ** the true branch is always executed!
2058   */
2059   
2060   usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2061   usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2062 }
2063
2064 void
2065 usymtab_popOrBranch (exprNode pred, exprNode expr)
2066   /*@modifies utab@*/
2067 {
2068   bool mustReturn;
2069   usymtab env = utab->env;
2070   usymtab otab = utab;
2071   int i = 0;
2072
2073   llassert (env != NULL);
2074
2075   if (exprNode_isError (expr))
2076     {
2077       mustReturn = FALSE;
2078     }
2079   else
2080     {
2081       mustReturn = exprNode_mustEscape (expr);
2082     }
2083
2084   
2085   llassert (utab->kind == US_TBRANCH);
2086
2087   /*
2088   ** merge each entry in table with its original
2089   ** unless execution cannot continue after this branch
2090   */
2091
2092   for (i = 0; i < utab->nentries; i++)
2093     {
2094       uentry current = utab->entries[i];
2095       uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2096
2097       uentry_mergeState (old, current, exprNode_loc (expr), 
2098                          mustReturn, FALSE, TRUE, ORCLAUSE);
2099     }
2100   
2101   
2102   if (mustReturn)
2103     {
2104       env->guards = guardSet_levelUnionFree (env->guards, 
2105                                              guardSet_invert (exprNode_getGuards (pred)), 
2106                                              env->lexlevel);
2107     }
2108   else
2109     {
2110       env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2111     }
2112  
2113   /* env is now utab */
2114   usymtab_quietPlainExitScope ();
2115 }
2116
2117 /*
2118 ** case syntax in C is very unrestricted.  This is unfortunate.
2119 **
2120 ** A switch case is ended either by a new case or default, or
2121 ** a close } that may close the switch or some other control
2122 ** structure.  
2123 */
2124
2125 bool
2126 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2127   /*@modifies utab@*/
2128 {
2129   bool mustBreak = usymtab_mustBreak (utab);
2130   bool mustReturn = usymtab_mustEscape (utab);
2131   usymtab stab = utab;
2132
2133   /*
2134   ** Find last case (or outer switch)
2135   */
2136
2137   while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2138     {
2139       stab = stab->env;
2140       llassert (stab != GLOBAL_ENV);
2141     }
2142
2143   /* ??? */
2144
2145   while (stab->kind == US_CBRANCH)
2146     {
2147       stab = stab->env;
2148       llassert (stab != GLOBAL_ENV);
2149     }
2150   
2151   /*
2152   ** if its a fall through case, merge in outside entries and last case.
2153   **
2154   ** e.g.,
2155   **        ...
2156   **        switch
2157   **          case 1: x = 3; <fall through>
2158   **          case 2: << x may not be defined
2159   **
2160   */
2161
2162   if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2163     {
2164       llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2165
2166       usymtab_entries (utab, ue)  /* but, keep track of used variables */
2167         {
2168           uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2169
2170           llassert (uentry_isValid (old));
2171
2172           /* modifies ue, not old */
2173           
2174           uentry_mergeState (ue, old, exprNode_loc (last),
2175                              FALSE, FALSE, TRUE, CASECLAUSE); 
2176         } end_usymtab_entries;
2177
2178       utab->aliases = aliasTable_levelUnion (utab->aliases, 
2179                                              stab->aliases, utab->lexlevel);
2180       
2181       /* 
2182       ** No need for a new branch.
2183       */
2184       
2185       return FALSE;
2186     }
2187   else
2188     {
2189       usymtab_caseBranch ();
2190       /*@-mustfree@*/ /*< utab->aliases >*/
2191       utab->aliases = aliasTable_copy (stab->aliases);
2192       /*@=mustfree@*/
2193       
2194       return TRUE;
2195     }
2196 }
2197
2198 /*
2199 ** for && (both pred and expr are executed)
2200 */
2201
2202 void
2203 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2204   /*@modifies utab@*/
2205 {
2206   usymtab env = utab->env;
2207   usymtab otab= utab;
2208   int i = 0;
2209
2210     llassert (utab->kind == US_TBRANCH);
2211
2212   /*
2213   ** merge each entry in table with its original
2214   ** unless execution cannot continue after this branch
2215   */
2216
2217   for (i = 0; i < utab->nentries; i++)
2218     {
2219       uentry current = utab->entries[i];
2220       sRef   tref = uentry_getSref (current);
2221       uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2222       sRef   oref = uentry_getSref (old);
2223
2224       /* note that is current is in a nested branch,
2225          it may create a "new" old entry. */
2226
2227       llassert (uentry_isValid (old));
2228       uentry_mergeState (old, current, exprNode_loc (expr), 
2229                          FALSE, FALSE, TRUE, ANDCLAUSE);
2230
2231       /*
2232       ** if is it defined by the second clause, then it should be defined.
2233       */
2234
2235       if (sRef_isAnyDefined (tref)
2236           && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2237         {
2238           sRef_setDefined (oref, g_currentloc);
2239         }
2240     }
2241
2242   utab->guards = guardSet_levelUnionFree (utab->guards, 
2243                                           guardSet_invert (exprNode_getGuards (pred)), 
2244                                           utab->lexlevel);
2245   utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2246
2247   usymtab_quietPlainExitScope ();
2248
2249   }
2250
2251 /*
2252 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2253 ** Only branches which do not return (except possibly the last branch) are included.
2254 **
2255 ** Conditionally merge state from all CBRANCHes.
2256 **
2257 ** If allpaths is TRUE, then all possible executions go through some switch 
2258 ** case, and the original scope is not merged.
2259 */
2260
2261 void
2262 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2263   /*@modifies utab@*/
2264 {
2265   usymtab ttab = utab;
2266   usymtab stab = ttab;
2267   usymtab ltab = ttab;
2268   bool lastMustReturn = usymtab_mustEscape (utab);
2269   int i;
2270   
2271     
2272   while (stab->kind == US_CBRANCH)
2273     {
2274       stab = stab->env;
2275       llassert (stab != GLOBAL_ENV);
2276     }
2277
2278   while (stab->kind == US_NORMAL)
2279     {
2280       stab = stab->env;
2281       llassert (stab != GLOBAL_ENV);
2282     }
2283
2284   llassert (stab->kind == US_SWITCH);
2285
2286   /* go to the scope outside the switch (US_SWITCH is just a marker! */
2287   stab = stab->env; 
2288   llassert (stab != GLOBAL_ENV);
2289
2290   
2291   ttab = ttab->env;
2292   llassert (usymtab_isDefined (ttab));
2293   
2294   if (ttab->kind == US_CBRANCH)
2295     {
2296       /* was quietPlainExitScope --- but, can't free it yet! */
2297       utab = utab->env;
2298       llassert (utab != GLOBAL_ENV);
2299
2300       while (ttab->kind == US_CBRANCH)
2301         {
2302           /*
2303           ** (from popTrueBranch)
2304           */      
2305           
2306           bool mustReturn = usymtab_mustEscape (ttab);
2307           bool mustBreak = usymtab_mustBreak (ttab);
2308           
2309           usymtab_entries (ttab, current)
2310             {
2311               uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2312                            /*@=compmempass@*/ 
2313               
2314               /*
2315               ** note that is this is in a nested branch,
2316               ** it may create a "new" old entry. 
2317               */
2318            
2319               if (uentry_isValid (old))
2320                 {
2321                   if (lastMustReturn)
2322                     {
2323                       uentry_mergeUses (current, old);
2324                       uentry_setState (old, current);
2325                     }
2326                   else
2327                     {
2328                       uentry_mergeState (old, current, exprNode_loc (sw),
2329                                          mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2330                     }
2331                 }
2332               else
2333                 {
2334                   ;
2335                 }
2336             } end_usymtab_entries;
2337           
2338           /*
2339           ** if entry is not in symbol table for this case, merge with pre-switch
2340           ** table
2341           */
2342           
2343           if (!mustReturn && !mustBreak)
2344             {
2345               usymtab_entries (stab, current)
2346                 {
2347                   if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2348                     {
2349                       uentry old = /*@-compmempass@*/
2350                         usymtab_lookupAux (ltab, uentry_rawName (current));
2351                       /*@=compmempass@*/
2352
2353                       llassert (uentry_isValid (old));
2354                       uentry_mergeState (old, current, exprNode_loc (sw),
2355                                          FALSE, FALSE, TRUE, SWITCHCLAUSE);
2356                     }
2357                 } end_usymtab_entries;
2358             }
2359           
2360           ltab->env = ttab->env; 
2361           ttab = ltab->env;
2362
2363           /*
2364           ** Suprious error, becuase of environments.
2365           */
2366
2367           /*@i1@*/ utab = ltab;
2368
2369           lastMustReturn = FALSE;
2370           /*@-branchstate@*/ 
2371         }
2372     }
2373   /*@=branchstate@*/
2374
2375   /*
2376   ** now, there is one US_CBRANCH.  Merge this with the stab.
2377   */
2378   
2379     
2380   for (i = 0; i < ltab->nentries; i++)
2381     {
2382       uentry current = ltab->entries[i];
2383       uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2384       
2385       /* note that is this is in a nested branch,
2386          it may create a "new" old entry. */
2387       
2388          
2389       if (uentry_isValid (old))
2390         {
2391           if (allpaths)
2392             {
2393               uentry_mergeUses (current, old);
2394               uentry_setState (old, current);
2395             }
2396           else
2397             {
2398               uentry_mergeState (old, current, exprNode_loc (sw), 
2399                                  FALSE, FALSE, TRUE, SWITCHCLAUSE);
2400             }
2401         }
2402       else
2403         {
2404                 }
2405     }
2406   
2407   /*
2408   ** exit the switch
2409   */
2410   
2411   
2412   /*
2413   ** switch may or may not be followed by a new scope
2414   */
2415
2416   if (utab->kind == US_SWITCH)
2417     {
2418       usymtab_quietPlainExitScope ();  
2419     }
2420   else
2421     {
2422       usymtab_quietPlainExitScope ();
2423       llassert (utab->kind == US_SWITCH);
2424       usymtab_quietPlainExitScope ();   
2425     }
2426
2427   }
2428
2429 static void 
2430 updateNullState (sRef el, /*@notnull@*/ usymtab ttab, 
2431                  /*@notnull@*/ usymtab ftab, bool trueGuard)
2432 {
2433   sRef base = sRef_getRootBase (el);
2434   int level = sRef_lexLevel (base);
2435   
2436         
2437     
2438   if (sRef_isCvar (base))
2439     {
2440       usymId index = sRef_getScopeIndex (base);
2441       uentry ue = usymtab_getRefTab (ttab, level, index);
2442
2443       if (!uentry_isLset (ue)) 
2444         {
2445           sRef sr = uentry_getSref (ue);
2446
2447           if (trueGuard)
2448             {
2449               sRef_setDerivNullState (sr, el, NS_NOTNULL);
2450             }
2451           else 
2452             {
2453               if (!guardSet_isGuarded (ttab->guards, el) 
2454                   && !sRef_isNotNull (sr))
2455                 {
2456                   sRef_setDerivNullState (sr, el, NS_DEFNULL);
2457                                 }
2458             }
2459         }
2460       else
2461         {
2462                 }
2463       
2464       ue = usymtab_getRefTab (ftab, level, index);
2465       
2466       if (!uentry_isLset (ue)) 
2467         {
2468           sRef sr = uentry_getSref (ue);
2469           
2470           
2471           if (!trueGuard) /* yikes!  forgot the ! */
2472             {
2473               sRef_setDerivNullState (sr, el, NS_NOTNULL);
2474             }
2475           else 
2476             {
2477               
2478               if (!guardSet_isGuarded (ftab->guards, el)
2479                   && !sRef_isNotNull (sr))
2480                 {
2481                   sRef_setDerivNullState (sr, el, NS_DEFNULL);
2482                                 }
2483             }
2484         }
2485       else
2486         {
2487                 }
2488       
2489           }
2490
2491       }
2492
2493 void
2494 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch, 
2495                      bool isOpt, clause cl)
2496      /*@modifies utab@*/
2497 {
2498   int i = 0;
2499   usymtab ftab = utab;
2500   usymtab ttab = utab->env;
2501
2502   fileloc loc;
2503   usymtab env;
2504   guardSet guards = exprNode_getGuards (pred);
2505   sRefSet tguards = guardSet_getTrueGuards (guards);
2506   sRefSet fguards = guardSet_getFalseGuards (guards);
2507   bool mustReturnT = exprNode_mustEscape (tbranch);
2508   bool mustReturnF = exprNode_mustEscape (fbranch);
2509   
2510   if (exprNode_isDefined (fbranch))
2511     {
2512       loc = exprNode_loc (fbranch);
2513     }
2514   else
2515     {
2516       loc = exprNode_loc (tbranch);
2517     }
2518
2519   llassert (usymtab_isDefined (ttab));
2520   
2521   env = ttab->env;
2522   
2523   llassert (usymtab_isDefined (env));
2524   llassert (ftab->kind == US_FBRANCH);
2525   llassert (ttab->kind == US_TBRANCH);
2526
2527   /*
2528   ** For each element that is true guarded (i.e., if (x != NULL)) 
2529   **          make x = null in false branch,
2530   **          and x = notnull in true branch.
2531   **          unless x was set locally in that branch.
2532   ** For each element that is false guarded (x == NULL) 
2533   **          make x = null in true, notnull in false.
2534   **                      
2535   ** For each element that is either guarded (pred(x)) 
2536   **     
2537   */
2538   
2539   sRefSet_allElements (tguards, el)
2540     {
2541       updateNullState (el, ttab, ftab, TRUE);
2542     } end_sRefSet_allElements;
2543     
2544   sRefSet_allElements (fguards, el)
2545     {
2546       updateNullState (el, ttab, ftab, FALSE);
2547     } end_sRefSet_allElements;
2548
2549   /*
2550   ** 
2551   ** if an entry is in both true and false, merge the entries,
2552   ** then replace original with new state.
2553   **
2554   ** if an entry is in one table, merge it with the original.
2555   */
2556     
2557   for (i = 0; i < ftab->nentries; i++)
2558     {
2559       uentry fthis = ftab->entries[i];
2560       uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
2561       int    tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
2562       
2563       if (uentry_isUndefined (old))
2564         {
2565           /* possible entry was added as an undefined id */
2566           continue;
2567         }
2568       
2569       if (tindex != NOT_FOUND)
2570         {
2571           uentry tthis = ttab->entries[tindex];
2572           
2573           /* note that is this is in a nested branch,
2574              it may create a "new" old entry. */
2575           
2576           if (!mustReturnF)
2577             {
2578               if (!mustReturnT)
2579                 {
2580                   
2581                   uentry_mergeState (fthis, tthis, loc,
2582                                      mustReturnT, FALSE, FALSE, cl);
2583                 }
2584               else
2585                 {
2586                   uentry_mergeUses (fthis, tthis);
2587                 }
2588               
2589               uentry_setState (old, fthis);
2590               
2591               /*@-mustfree@*/ 
2592             } 
2593           /*@=mustfree@*/
2594           else
2595             {
2596               uentry_setState (old, tthis);
2597               uentry_mergeState (old, fthis, loc, mustReturnF, 
2598                                  TRUE, FALSE, cl);
2599             }
2600           
2601           ttab->entries[tindex] = uentry_undefined;
2602           uentry_free (tthis);
2603         }
2604       else
2605         {
2606           uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
2607         }
2608     }
2609
2610   for (i = 0; i < ttab->nentries; i++)
2611     {
2612       uentry current = ttab->entries[i];
2613       
2614       if (!uentry_isUndefined (current)) 
2615         {
2616           uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2617
2618           llassertprint (!uentry_isUndefined (old), ("name: <%s>", 
2619                                                      uentry_rawName (current)));
2620           if (mustReturnF)
2621             {
2622               uentry_mergeUses (current, old); 
2623               uentry_setState (old, current);
2624             }
2625           else
2626             {
2627               /*
2628               ** assumes false branch is a fall-through if
2629               ** fbranch is not defined.  This is true, unless
2630               ** where was some greivous error in processing
2631               ** the else branch of an if-then, in which case
2632               ** this is probably the right thing to do anyway.
2633               */
2634
2635               uentry_mergeState (old, current, loc, mustReturnT, 
2636                                  FALSE, isOpt, cl);
2637             }
2638         }
2639     }
2640
2641   
2642   /*
2643   ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
2644   ** if they are present.
2645   */
2646
2647   llassert (NOALIAS (env->aliases, ttab->aliases));
2648   llassert (NOALIAS (env->aliases, ftab->aliases));
2649
2650   aliasTable_free (env->aliases);  
2651
2652   env->aliases = aliasTable_levelUnionNew (ttab->aliases, 
2653                                            ftab->aliases, env->lexlevel);
2654
2655   aliasTable_fixSrefs (env->aliases);
2656   
2657   /* exit true and false scopes */
2658   usymtab_quietPlainExitScope ();
2659   usymtab_quietPlainExitScope ();
2660   
2661   if (mustReturnT)
2662     {
2663       utab->guards = guardSet_levelUnionFree 
2664         (utab->guards, 
2665          guardSet_invert (exprNode_getGuards (pred)), 
2666          utab->lexlevel);
2667     }
2668
2669   if (mustReturnF)
2670     {
2671       utab->guards = guardSet_levelUnion (utab->guards, 
2672                                           exprNode_getGuards (pred), 
2673                                           utab->lexlevel);
2674     }
2675
2676   DPRINTF (("Here."));
2677 }
2678
2679 static void usymtab_fixCases (void) /*@modifies utab@*/ {
2680   while (utab->kind == US_CBRANCH)
2681     {
2682       usymtab_quietPlainExitScope ();
2683     }
2684
2685   llassert (utab->kind != US_CBRANCH);
2686 }
2687
2688 void
2689 usymtab_altBranch (/*@only@*/ guardSet guards)
2690   /*@modifies utab@*/
2691 {
2692   usymtab t = usymtab_create (US_FBRANCH, utab, FALSE);
2693   usymtab parent = utab->env;
2694
2695   /*
2696   ** If we are in a case, need to close it.  The C syntax
2697   ** is very liberal, so this kludge is necessary.
2698   */
2699
2700   usymtab_fixCases ();
2701
2702   DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
2703   llassert (utab->kind == US_TBRANCH);
2704   llassert (parent != GLOBAL_ENV);
2705
2706   guardSet_free (t->guards);
2707   t->guards = guards;
2708
2709   aliasTable_free (t->aliases);
2710   t->aliases = aliasTable_copy (parent->aliases);
2711     
2712   utab = t;
2713 }
2714
2715 void
2716 usymtab_allDefined (void)
2717    /*@globals utab, globtab@*/
2718 {
2719   int i;
2720
2721   llassert (utab == globtab);
2722
2723   for (i = 0; i < utab->nentries; i++)
2724     {
2725       uentry e = utab->entries[i];
2726
2727       if (uentry_isPriv (e))
2728         {
2729          ; /* no need to define it */
2730         }
2731       else
2732         {
2733           if (context_getFlag (FLG_SPECUNDECL))
2734             {
2735               fileloc sloc = uentry_whereSpecified (e);
2736               fileloc dloc = uentry_whereDeclared (e);
2737
2738               if (fileloc_isDefined (sloc) 
2739                   && !uentry_isFakeTag (e)
2740                   && !fileloc_isDefined (dloc))
2741                 {
2742                   voptgenerror 
2743                     (FLG_SPECUNDECL,
2744                      message ("%s %q specified but not declared",
2745                               ekind_capName (uentry_getKind (e)),
2746                               uentry_getName (e)),
2747                      sloc);
2748                 }
2749             }
2750           
2751           if (!uentry_isCodeDefined (e))
2752             {
2753               fileloc dloc = uentry_whereDeclared (e);
2754               
2755               if (fileloc_isLib (dloc))
2756                 {
2757                  ;
2758                 }
2759               else if (fileloc_isDefined (dloc))
2760                 {
2761                   if (!uentry_isAnyTag (e))
2762                     {
2763                       if (fileloc_isUser (dloc))
2764                         {
2765                           voptgenerror 
2766                             (FLG_DECLUNDEF,
2767                              message ("%s %q declared but not defined",
2768                                       ekind_capName (uentry_getKind (e)),
2769                                       uentry_getName (e)),
2770                              dloc);
2771                         }
2772                     }
2773                 }
2774               else
2775                 {
2776                   fileloc sloc = uentry_whereSpecified (e);
2777
2778                   if (fileloc_isDefined (sloc) 
2779                       && !fileloc_isImport (sloc)
2780                       && !fileloc_isLib (sloc)
2781                       && !fileloc_isPreproc (sloc)
2782                       && !uentry_isFakeTag (e))
2783                     {
2784                       if (uentry_isVariable (e) || uentry_isFunction (e))
2785                         {
2786                           voptgenerror 
2787                             (FLG_SPECUNDEF,
2788                              message ("%s %q specified but not declared or defined",
2789                                       ekind_capName (uentry_getKind (e)),
2790                                       uentry_getName (e)),
2791                              sloc);
2792                         }
2793                       else
2794                         {
2795                           voptgenerror 
2796                             (FLG_SPECUNDEF,
2797                              message ("%s %q specified but not defined",
2798                                       ekind_capName (uentry_getKind (e)),
2799                                       uentry_getName (e)),
2800                              sloc);
2801                         }
2802                     }
2803                 }
2804             }
2805         }
2806     }
2807 }
2808
2809 void usymtab_exportHeader (void)
2810      /*@globals utab@*/
2811 {
2812   int i;
2813
2814   for (i = 0; i < utab->nentries; i++)
2815     {
2816       uentry ce = utab->entries[i];
2817
2818       if (!uentry_isDatatype (ce) 
2819           && !uentry_isAnyTag (ce) 
2820           && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
2821           && !uentry_isExternal (ce)
2822           && !uentry_isForward (ce))
2823         {
2824           fileloc fwhere = uentry_whereDeclared (ce);
2825
2826           if (fileloc_isUndefined (fwhere)
2827               && uentry_isFunction (ce))
2828             {
2829               fwhere = uentry_whereDefined (ce);
2830             }
2831
2832           if (fileloc_isDefined (fwhere) 
2833               && !fileloc_isHeader (fwhere)
2834               && !(fileloc_isSpecialFile (fwhere)
2835                    && !context_getFlag (FLG_UNUSEDSPECIAL)))
2836             {
2837               if (uentry_isVariable (ce))
2838                 {
2839                   if (optgenerror
2840                       (FLG_EXPORTHEADERVAR,
2841                        message ("%s %q exported but not declared in header file", 
2842                                 ekind_capName (uentry_getKind (ce)),
2843                                 uentry_getName (ce)),
2844                        fwhere))
2845                     {
2846                       uentry_showDefSpecInfo (ce, fwhere);
2847                     }
2848                 }
2849               else
2850                 {
2851                   if (!uentry_isIter (ce)
2852                       && !uentry_isEndIter (ce)
2853                       && !uentry_isExpandedMacro (ce))
2854                     {
2855                       if (uentry_isFunction (ce) 
2856                           && cstring_equalLit (uentry_rawName (ce), "main"))
2857                         {
2858                           ; /* no error for main */
2859                         }
2860                       else
2861                         {
2862                           if (optgenerror
2863                               (FLG_EXPORTHEADER,
2864                                message ("%s %q exported but not declared "
2865                                         "in header file", 
2866                                         ekind_capName (uentry_getKind (ce)),
2867                                         uentry_getName (ce)),
2868                                fwhere))
2869                             {
2870                               uentry_showDefSpecInfo (ce, fwhere);
2871                             }
2872                         }
2873                     }
2874                 }
2875             }
2876         }
2877     }
2878 }
2879
2880 void usymtab_exportLocal (void)
2881    /*@globals utab@*/
2882 {
2883   int i;
2884
2885   
2886   for (i = 0; i < utab->nentries; i++)
2887     {
2888       uentry ce = utab->entries[i];
2889
2890       
2891       if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce) 
2892           && !uentry_isEitherConstant (ce) 
2893           && !uentry_isIter (ce)
2894           && !uentry_isEndIter (ce)
2895           && !uentry_isExpandedMacro (ce)
2896           && uentry_isUsed (ce))
2897         {
2898           /* check static uses */
2899           filelocList fuses = uentry_getUses (ce);
2900           fileloc mod = uentry_whereDefined (ce);
2901           bool ok = filelocList_isEmpty (fuses);
2902           fileloc fwhere = uentry_whereDeclared (ce);
2903
2904           if (fileloc_isSpecialFile (fwhere)
2905               && !context_getFlag (FLG_UNUSEDSPECIAL))
2906             {
2907               ok = TRUE; /* no errors for special files */
2908             }
2909           else
2910             {
2911               filelocList_elements (fuses, uloc)
2912                 {
2913                   if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
2914                     {
2915                       ok = TRUE;
2916                       /*@innerbreak@*/ break;
2917                     }
2918                 } end_filelocList_elements;
2919             }
2920
2921           if (!ok)
2922             {
2923               if (optgenerror
2924                   (FLG_EXPORTLOCAL,
2925                    message ("%s exported but not used outside %s: %q", 
2926                             ekind_capName (uentry_getKind (ce)),
2927                             fileloc_getBase (mod),
2928                             uentry_getName (ce)),
2929                    fwhere))
2930                 {
2931                   uentry_showDefSpecInfo (ce, fwhere);
2932                 }
2933             }
2934         }
2935     }
2936 }
2937
2938 void
2939 usymtab_allUsed (void)
2940   /*@globals utab@*/
2941 {
2942   int i;
2943   bool isFileStatic = usymtab_inFileScope ();
2944   cstring last_file = cstring_undefined;
2945
2946   for (i = 0; i < utab->nentries; i++)
2947     {
2948       bool hasError = FALSE;
2949       uentry ce = utab->entries[i];
2950       fileloc fwhere = uentry_whereDeclared (ce);
2951
2952       if (fileloc_isUndefined (fwhere))
2953         {
2954           fwhere = uentry_whereDefined (ce);
2955         }
2956
2957       if (fileloc_isInvalid (fwhere) 
2958           || fileloc_isLib (fwhere) 
2959           || fileloc_isBuiltin (fwhere)
2960           || ((fileloc_isSpecialFile (fwhere)
2961                || fileloc_isSpecialFile (uentry_whereDefined (ce)))
2962               && !context_getFlag (FLG_UNUSEDSPECIAL)))
2963         {
2964           ;
2965         }
2966       else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
2967         {
2968           cstring fname = fileloc_filename (fwhere);
2969
2970           if (cstring_isUndefined (last_file))
2971             {
2972               last_file = fname;
2973             }
2974           else if (cstring_equal (fname, last_file))
2975             {
2976             }
2977           else
2978             {
2979               cleanupMessages ();
2980               last_file = fname;
2981             } 
2982           
2983           if (uentry_isParam (ce))
2984             {
2985               if (context_inMacro ())
2986                 {
2987                   sRef cref = uentry_getSref (ce);
2988
2989                   if (uentry_isYield (ce))
2990                     {
2991                       ; /* no checks (for now) */
2992                     }
2993                   else if (sRef_isSafe (cref))
2994                     {
2995                       ; /* no error */
2996                     }
2997                   else
2998                     {
2999                       if (uentry_hasRealName (ce))
3000                         {
3001                           hasError = 
3002                             optgenerror (FLG_MACROPARAMS,
3003                                          message ("Macro parameter %q not used", 
3004                                                   uentry_getName (ce)),
3005                                          fwhere);
3006                         }
3007                     }
3008                 }
3009               else 
3010                 {
3011                   if (cstring_equalFree (uentry_getName (ce), 
3012                                          cstring_makeLiteral ("...")))
3013                     {
3014                       ;
3015                     }
3016                   else
3017                     {
3018                       hasError = optgenerror (FLG_PARAMUNUSED,
3019                                               message ("Parameter %q not used",
3020                                                        uentry_getName (ce)),
3021                                               fwhere);
3022                     }
3023                 }
3024             } /* isParam */
3025           else if (uentry_isFunction (ce) || uentry_isIter (ce))
3026             {
3027               if (fileloc_isUser (fwhere))
3028                 {
3029                   hasError = optgenerror
3030                     (FLG_FUNCUNUSED, 
3031                      message ("%q %q declared but not used", 
3032                               cstring_makeLiteral 
3033                               (uentry_isIter (ce) ? "Iterator" 
3034                                : (isFileStatic ? "File static function" : "Function")),
3035                               uentry_getName (ce)),
3036                      fwhere);
3037                 }
3038             }
3039           else if (uentry_isEndIter (ce))
3040             {
3041               ; /* no error (already reported for iter */
3042             }
3043           else if (uentry_isEnumConstant (ce))
3044             {
3045               if (fileloc_isUser (fwhere))
3046                 {
3047                   hasError = optgenerror
3048                     (FLG_ENUMMEMUNUSED,
3049                      message ("Enum member %q not used", 
3050                               uentry_getName (ce)),
3051                      fwhere);
3052                 }
3053             }
3054           else if (uentry_isConstant (ce))
3055             {
3056               if (fileloc_isUser (fwhere))
3057                 {
3058                   hasError = optgenerror
3059                     (FLG_CONSTUNUSED,
3060                      message ("Constant %q declared but not used", 
3061                               uentry_getName (ce)),
3062                      fwhere);
3063                 }
3064             }
3065           else if (uentry_isDatatype (ce))
3066             {
3067               if (fileloc_isUser (fwhere))
3068                 {
3069                   hasError = optgenerror
3070                     (FLG_TYPEUNUSED,
3071                      message ("Type %q declared but not used", 
3072                               uentry_getName (ce)),
3073                      fwhere);
3074                 }
3075             }
3076           else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3077             { /* errors for ref params will be reported in the next scope */
3078               llassertprint (uentry_isVar (ce), 
3079                              ("ce: %s", uentry_unparseFull (ce)));
3080
3081               if (ctype_isFunction (uentry_getType (ce)))
3082                 {
3083                   if (fileloc_isUser (fwhere))
3084                     {
3085                       hasError = optgenerror
3086                         (FLG_FUNCUNUSED,
3087                          message ("%q %q declared but not used", 
3088                                   cstring_makeLiteral 
3089                                   (isFileStatic ? "File static function" 
3090                                    : "Function"),
3091                                   uentry_getName (ce)),
3092                          fwhere);
3093                     }
3094                 }
3095               else 
3096                 {
3097                   if (fileloc_isUser (fwhere))
3098                     {
3099                       
3100                       
3101                       hasError = optgenerror 
3102                         (FLG_VARUNUSED,
3103                          message ("%q %q declared but not used", 
3104                                   cstring_makeLiteral 
3105                                   (isFileStatic ? "File static variable" 
3106                                    : "Variable"), 
3107                                   uentry_getName (ce)),
3108                          fwhere);
3109                     }
3110                 }
3111             }
3112           else
3113             {
3114               ; /* no errors */
3115             }
3116         } /* unused */
3117       else if (uentry_isDatatype (ce) || uentry_isAnyTag (ce))
3118         { /* check all fields */
3119           ctype ct = uentry_getRealType (ce); 
3120
3121           
3122           while (ctype_isAP (ct))
3123             {
3124               ct = ctype_getBaseType (ct);
3125             }
3126
3127           
3128           if (ctype_isSU (ct))
3129             {
3130               uentryList fields = ctype_getFields (ct);
3131
3132               uentryList_elements (fields, field)
3133                 {
3134                   if (!uentry_isUsed (field))
3135                     {
3136                       if (uentry_hasName (ce))
3137                         {
3138                           hasError |= optgenerror 
3139                             (FLG_FIELDUNUSED,
3140                              message ("Field %q of %s %q declared but not used", 
3141                                       uentry_getName (field),
3142                                       cstring_makeLiteralTemp
3143                                       (ctype_isStruct (ct) ? "structure" : "union"),
3144                                       uentry_getName (ce)),
3145                              uentry_whereEarliest (field));
3146                         }
3147                       else
3148                         {
3149                           hasError |= optgenerror 
3150                             (FLG_FIELDUNUSED,
3151                              message ("Field %q of unnamed %s declared but not used", 
3152                                       uentry_getName (field),
3153                                       cstring_makeLiteralTemp
3154                                       (ctype_isStruct (ct) ? "structure" : "union")),
3155                              uentry_whereEarliest (field));
3156                         }
3157                       
3158                       uentry_setUsed (field, fileloc_undefined);
3159                     }
3160                 } end_uentryList_elements;
3161             }
3162         }
3163       else
3164         {
3165           ; /* no errors */
3166         }
3167
3168       if (hasError)
3169         {
3170           if (uentry_isParam (ce) && context_inMacro ())
3171             {
3172               if (fileloc_isDefined (uentry_whereSpecified (ce)))
3173                 {
3174                   uentry_showWhereSpecified (ce);
3175                 }
3176             }
3177           else
3178             {
3179               uentry_showDefSpecInfo (ce, fwhere);
3180             }
3181
3182           uentry_setUsed (ce, fileloc_undefined);
3183         }
3184     }
3185 }
3186
3187 static void
3188 checkGlobalReturn (uentry glob, sRef orig)
3189 {
3190   sRef sr = uentry_getSref (glob);
3191   
3192   
3193   if (context_getFlag (FLG_GLOBSTATE))
3194     {
3195       if (sRef_isKilledGlob (orig))
3196         {
3197           if (sRef_isStateUndefined (sr)
3198               || sRef_isUnuseable (sr)
3199               || sRef_isStateUnknown (sr)
3200               || sRef_isDead (sr))
3201             {
3202               ;
3203             }
3204           else
3205             {
3206               ctype ct = ctype_realType (uentry_getType (glob));
3207
3208               if (ctype_isVisiblySharable (ct))
3209                 {
3210                   if (optgenerror 
3211                       (FLG_GLOBSTATE,
3212                        message 
3213                        ("Killed global %q not released before return",
3214                         uentry_getName (glob)),
3215                        g_currentloc))
3216                     {
3217                       sRef_showStateInfo (sr);
3218                                     }
3219                 }
3220               else
3221                 {
3222                                   sRef_protectDerivs ();
3223                   (void) checkGlobalDestroyed (sr, g_currentloc);
3224                   sRef_clearProtectDerivs ();
3225                 }
3226             }
3227         }
3228       else
3229         {
3230           if (sRef_isStateUndefined (sr))
3231             {
3232               if (optgenerror (FLG_GLOBSTATE,
3233                                message 
3234                                ("Function returns with global %q undefined",
3235                                 uentry_getName (glob)),
3236                                g_currentloc))
3237                 {
3238                   sRef_showStateInfo (sr);
3239                 }
3240             }
3241           else 
3242             {
3243               if (sRef_isDead (sr))
3244                 {
3245                   if (optgenerror 
3246                       (FLG_GLOBSTATE,
3247                        message ("Function returns with global %q "
3248                                 "referencing released storage",
3249                                 uentry_getName (glob)),
3250                        g_currentloc))
3251                     {
3252                       sRef_showStateInfo (sr);
3253                       sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3254                     }
3255                 }
3256               
3257               if (ctype_isRealPointer (uentry_getType (glob)) &&
3258                   sRef_possiblyNull (sr) && !uentry_possiblyNull (glob))
3259                 {
3260                   if (optgenerror 
3261                       (FLG_GLOBSTATE,
3262                        message ("Function returns with non-null global %q "
3263                                 "referencing null storage",
3264                                 uentry_getName (glob)),
3265                        g_currentloc))
3266                     {
3267                       sRef_showNullInfo (sr);
3268                     }
3269                 }
3270               else
3271                 {
3272                   checkGlobReturn (glob);
3273                 }
3274             }
3275         }
3276     }
3277 }
3278
3279 /*
3280 ** remember: check alias globals
3281 */
3282
3283 void usymtab_checkFinalScope (bool isReturn)
3284   /*@globals utab@*/
3285 {
3286   bool mustFree = context_getFlag (FLG_MUSTFREE);
3287   bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3288   /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3289   sRefSet checked = sRefSet_new ();
3290   usymtab stab = utab;
3291   int i;
3292     
3293   /*
3294   ** need to check all scopes out to function parameters.
3295   */
3296
3297   do 
3298     {
3299       for (i = 0; i < stab->nentries; i++)
3300         {
3301           uentry ce = stab->entries[i];
3302           sRef sr = uentry_getSref (ce);
3303           sRef rb = sRef_getRootBase (sr);
3304
3305           if (ctype_isFunction (uentry_getType (ce)))
3306             {
3307               /*@innercontinue@*/ continue;
3308             }
3309
3310           if (mustFree)
3311             {
3312               DPRINTF (("Check entry: %s", uentry_unparseFull (ce)));
3313
3314               if (!sRefSet_member (checked, sr) && !sRef_isGlobal (rb))
3315                 {
3316                   if (ctype_isRealSU (uentry_getType (ce))
3317                       && !uentry_isAnyParam (ce)
3318                       && !uentry_isRefParam (ce)
3319                       && !uentry_isStatic (ce)
3320                       && !sRef_isDependent (sr)
3321                       && !sRef_isOwned (sr))
3322                     {
3323                       sRefSet als = usymtab_allAliases (sr);
3324
3325                       
3326                       if (sRefSet_isEmpty (als))
3327                         {
3328                           checkLocalDestroyed (sr, g_currentloc);
3329                         }
3330                       else
3331                         {
3332                           /* aliased, no problem */ ;
3333                         }
3334
3335                       sRefSet_free (als);
3336                     }
3337                   else if
3338                     (!uentry_isStatic (ce)
3339                      && ((sRef_isNewRef (sr))
3340                          || (((sRef_isOnly (sr) || sRef_isFresh (sr) 
3341                                || sRef_isKeep (sr) || sRef_isOwned (sr))
3342                               && !sRef_isDead (sr))
3343                              && (!sRef_definitelyNull (sr))
3344                              && (!usymtab_isProbableNull (sr)))))
3345                       {
3346                         bool hasError = TRUE;
3347                         
3348                         /*
3349                         ** If its a scope exit, check if there is an alias.
3350                         ** If so, make it only.  If not, there is an error.
3351                         */
3352                         
3353                         if (!isReturn)
3354                           {
3355                             if (canLoseReference (sr, g_currentloc))
3356                               {
3357                                 hasError = FALSE;
3358                               }
3359                           }
3360                         
3361                         if (hasError)
3362                           {
3363                             if (sRef_hasLastReference (sr))
3364                               {
3365                                 sRef ar = sRef_getAliasInfoRef (sr);
3366                                 
3367                                 if (optgenerror 
3368                                     (FLG_MUSTFREE,
3369                                      message
3370                                      ("Last reference %q to %s storage %qnot %q before %q",
3371                                       sRef_unparse (sr),
3372                                       alkind_unparse (sRef_getAliasKind (sr)),
3373                                       sRef_unparseOpt (ar),
3374                                       cstring_makeLiteral (sRef_isKeep (sr) 
3375                                                            ? "transferred" : "released"),
3376                                       cstring_makeLiteral (isReturn 
3377                                                            ? "return" : "scope exit")),
3378                                      g_currentloc))
3379                                   {
3380                                     sRef_showRefLost (sr);
3381                                   }
3382                               }
3383                             else if (sRef_isNewRef (sr))
3384                               {
3385                                 if (optgenerror
3386                                     (FLG_MUSTFREE,
3387                                      message 
3388                                      ("%q %q not released before %q",
3389                                       cstring_makeLiteral 
3390                                       (alkind_isKillRef (sRef_getOrigAliasKind (sr))
3391                                        ? "Kill reference parameter" : "New reference"),
3392                                       uentry_getName (ce),
3393                                       cstring_makeLiteral (isReturn
3394                                                            ? "return" : "scope exit")),
3395                                      g_currentloc))
3396                                   {
3397                                     sRef_showAliasInfo (sr);
3398                                   }
3399                               }
3400                             else 
3401                               {
3402                                 if (ctype_isRealSU (sRef_getType (sr)))
3403                                   {
3404                                                                     checkStructDestroyed (sr, g_currentloc);
3405                                   }
3406                                 else
3407                                   {
3408                                     if (optgenerror
3409                                         (FLG_MUSTFREE,
3410                                          message 
3411                                          ("%s storage %q not %q before %q",
3412                                           alkind_capName (sRef_getAliasKind (sr)),
3413                                           uentry_getName (ce),
3414                                           cstring_makeLiteral (sRef_isKeep (sr) 
3415                                                                ? "transferred" : "released"),
3416                                           cstring_makeLiteral (isReturn 
3417                                                                ? "return" : "scope exit")),
3418                                          g_currentloc))
3419                                       {
3420                                         sRef_showAliasInfo (sr);
3421                                       }
3422                                   }
3423                               }
3424                           }
3425                       }
3426                   else
3427                     {
3428                       ;
3429                     }
3430                 }
3431               else if (mustDefine && uentry_isOut (ce))
3432                 {
3433                   if (!ynm_toBoolStrict (sRef_isReadable (sr)))
3434                     {
3435                       voptgenerror 
3436                         (FLG_MUSTDEFINE,
3437                          message ("Out storage %q not defined before %q",
3438                                   uentry_getName (ce),
3439                                   cstring_makeLiteral 
3440                                   (isReturn ? "return" : "scope exit")),
3441                          g_currentloc);
3442                       
3443                       /* uentry_showWhereDeclared (ce); */
3444                     }
3445                 }
3446               else
3447                 {
3448                   ; 
3449                 }
3450               
3451               /*
3452               ** also check state is okay
3453               */
3454
3455               if (usymtab_lexicalLevel () > functionScope
3456                   && uentry_isVariable (ce)
3457                   && (sRef_isLocalVar (sr)
3458                       && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
3459                 {
3460                   sRefSet ab = usymtab_aliasedBy (sr);
3461
3462                   /* should do something more efficient here */
3463
3464                   if (sRefSet_isEmpty (ab))
3465                     {
3466                       /* and no local ref */
3467                       checkLoseRef (ce);
3468                     }
3469                   else
3470                     {
3471                       ;
3472                     }
3473                   
3474                   sRefSet_free (ab);
3475                 }
3476               else 
3477                 {
3478                   ;
3479                 }
3480               
3481               checked = sRefSet_insert (checked, sr);
3482             }
3483         }
3484       llassert (usymtab_isDefined (stab->env));
3485
3486       if (usymtab_isBranch (stab))
3487         {
3488           stab = usymtab_dropEnv (stab);
3489         }
3490       else
3491         {
3492           stab = stab->env;
3493         }
3494
3495       llassert (stab != usymtab_undefined);
3496     } while (isReturn && (stab->lexlevel >= paramsScope));
3497
3498     sRefSet_free (checked);
3499
3500   /*
3501   ** for returns:
3502   **      all globals are appropriately defined
3503   **      all parameters are appropriately defined
3504   **      special clauses are followed
3505   */
3506
3507   if (isReturn || (utab->lexlevel == paramsScope))
3508     {
3509       uentry fcn = context_getHeader ();
3510       uentryList params = context_getParams ();
3511       globSet uglobs = context_getUsedGlobs ();
3512       globSet sglobs = context_getGlobs ();
3513
3514             
3515       if (isReturn && context_maybeSet (FLG_GLOBALIAS))
3516         { 
3517           aliasTable_checkGlobs (utab->aliases); 
3518         }
3519
3520       /*
3521       ** special clauses (defines, sets, allocates, releases) 
3522       */
3523
3524       if (uentry_hasSpecialClauses (fcn))
3525         {
3526           specialClauses clauses = uentry_getSpecialClauses (fcn);
3527
3528           specialClauses_elements (clauses, cl)
3529             {
3530               if (specialClause_isAfter (cl)) 
3531                 { /* evs - 2000 07 10 - added this */
3532                   sRefTest tst = specialClause_getPostTestFunction (cl);
3533                   sRefSet rfs = specialClause_getRefs (cl);
3534                   
3535                   sRefSet_elements (rfs, el)
3536                     {
3537                       sRef base = sRef_getRootBase (el);
3538                       
3539                       if (sRef_isResult (base))
3540                         {
3541                           ; 
3542                         }
3543                       else if (sRef_isParam (base))
3544                         {
3545                           sRef sr = sRef_updateSref (base);
3546                           sr = sRef_fixBase (el, sr);
3547                           
3548                           if (tst != NULL && !tst (sr))
3549                             {
3550                               if (optgenerror 
3551                                   (specialClause_postErrorCode (cl),
3552                                    message ("%s storage %qcorresponds to "
3553                                             "storage listed in %q clause",
3554                                             specialClause_postErrorString (cl, sr),
3555                                             sRef_unparseOpt (sr),
3556                                             specialClause_unparseKind (cl)),
3557                                    g_currentloc))
3558                                 {
3559                                   sRefShower ss = specialClause_getPostTestShower (cl);
3560                                   
3561                                   if (ss != NULL)
3562                                     {
3563                                       ss (sr);
3564                                     }
3565                                 }  
3566                             }
3567                         }
3568                       else
3569                         {
3570                           if (sRef_isMeaningful (el))
3571                             {
3572                               BADBRANCH;
3573                             }
3574                         }
3575                     } end_sRefSet_elements ;
3576                 }
3577             } end_specialClauses_elements ;
3578         }
3579       
3580       /*
3581       ** check parameters on return
3582       */
3583
3584       uentryList_elements (params, arg)
3585         {
3586           if (!uentry_isElipsisMarker (arg))
3587             {
3588               ctype rt = ctype_realType (uentry_getType (arg));
3589
3590               if (ctype_isMutable (rt) || ctype_isSU (rt))
3591                 {
3592                   uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
3593                   checkParamReturn (param);
3594                 }
3595             }
3596         } end_uentryList_elements;
3597       
3598       globSet_allElements (sglobs, el)
3599         {
3600           uentry current = sRef_getUentry (el);
3601
3602           if (uentry_isVariable (current) && !uentry_isRealFunction (current))
3603             {
3604               checkGlobalReturn (current, el);
3605             }
3606         } end_globSet_allElements;
3607
3608       globSet_allElements (uglobs, el)
3609         {
3610           if (!globSet_member (sglobs, el))
3611             {
3612               uentry current = sRef_getUentry (el);
3613               
3614                       
3615               if (uentry_isVariable (current)
3616                   && !uentry_isRealFunction (current))
3617                 {
3618                   checkGlobalReturn (current, sRef_undefined);
3619                 }
3620             }
3621         } end_globSet_allElements;
3622     }
3623   
3624   }
3625
3626 void
3627 usymtab_quietExitScope (fileloc loc) 
3628    /*@globals utab, globtab, filetab; @*/ 
3629    /*@modifies utab@*/
3630 {
3631   usymtab t = utab->env;
3632
3633   if (utab->reftable != NULL)
3634     {
3635       int i;
3636
3637       for (i = 0; i < utab->nentries; i++)
3638         {
3639           uentry current = utab->entries[i];      
3640           uentry old = usymtab_lookupAux (t, uentry_rawName (current));
3641
3642           uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
3643         }
3644     }
3645
3646   llassert (t != NULL);
3647
3648   if (t->lexlevel > paramsScope)
3649     {
3650       t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
3651       t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases, 
3652                                              t->lexlevel);
3653       utab->aliases = aliasTable_undefined;
3654     }
3655
3656   t->mustBreak = utab->mustBreak;
3657   t->exitCode = utab->exitCode;
3658
3659   usymtab_freeLevel (utab);
3660
3661   utab = t;
3662 }
3663
3664 /*
3665 ** Exit a scope with no checking, lose alias states.
3666 ** (When should this be used?)
3667 */
3668
3669 void usymtab_quietPlainExitScope (void)
3670      /*@globals utab, globtab, filetab@*/
3671      /*@modifies utab@*/
3672 {
3673   usymtab t = utab->env;
3674
3675   llassert (t != NULL);
3676   llassert (NOALIAS (utab->aliases, t->aliases));
3677   usymtab_freeLevel (utab);
3678   utab = t;
3679 }
3680
3681 void usymtab_exitScope (exprNode expr)
3682   /*@globals utab, filetab, globtab@*/
3683   /*@modifies utab, globtab@*/
3684 {
3685   usymtab ctab = usymtab_undefined;
3686   usymtab lctab = usymtab_undefined;
3687   bool mustReturn = exprNode_mustEscape (expr);
3688   
3689   if (utab->kind == US_CBRANCH)
3690     {
3691       /*
3692       ** save the case branches, remove the first non-cbranch
3693       */
3694
3695       ctab = utab;
3696
3697       while (utab->kind == US_CBRANCH) 
3698         {
3699           lctab = utab;
3700           utab = utab->env;
3701           llassert (utab != GLOBAL_ENV);
3702         }
3703     }
3704   
3705   if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
3706       || utab->kind == US_CBRANCH || utab->kind == US_SWITCH) {
3707    
3708     if (context_inMacro ()) {
3709       /* evs 2000-07-25 */
3710       /* Unparseable macro may end inside nested scope.  Deal with it. */
3711       
3712       llerror (FLG_SYNTAX, message ("Problem parsing macro body of %s (unbalanced scopes).  Attempting to recover, recommend /*@notfunction@*/ before macro definition.", 
3713                                     context_inFunctionName ()));
3714       
3715       while (utab->kind == US_TBRANCH
3716              || utab->kind == US_FBRANCH
3717              || utab->kind == US_CBRANCH
3718              || utab->kind == US_SWITCH) 
3719         {
3720           utab = utab->env;
3721           llassert (utab != GLOBAL_ENV);
3722         }
3723     } else {
3724       llcontbug (("exitScope: in branch: %s", usymtab_unparseStack ()));
3725       /*@-branchstate@*/ 
3726     } /*@=branchstate@*/
3727   }
3728
3729   /*
3730   ** check all variables in scope were used
3731   */
3732
3733   /*
3734   ** bogus errors if this is the normal inside a switch,
3735   ** since cases have not been merged yet.  Should probably
3736   ** still check this, but I'm too lazy at the moment...
3737   */
3738
3739   llassertfatal (utab->env != GLOBAL_ENV);
3740
3741   if (utab->env->kind != US_SWITCH)
3742     {
3743       usymtab_allUsed ();
3744     }
3745
3746   /*
3747   ** check aliasing: all only params are released (dead)
3748   **     definition: all out params are defined, all modified params 
3749   **                     are completely defined
3750   **
3751   ** NOTE: note for exiting paramsScope, since checkReturn should be
3752   ** called first.
3753   */
3754
3755   if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
3756     {
3757       /*
3758       ** should only call this is end of scope is reachable...
3759       */
3760
3761       usymtab_checkFinalScope (FALSE);
3762     }
3763
3764   if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
3765     {
3766       /*
3767       ** leaving a function, need to fix up globals
3768       */
3769
3770       uentryList params = context_getParams ();
3771       globSet    globs = context_getUsedGlobs ();
3772
3773                   
3774       uentryList_elements (params, ue)
3775         {
3776           uentry_fixupSref (ue);
3777         } end_uentryList_elements;
3778
3779       clearFunctionTypes ();
3780
3781       
3782       globSet_allElements (globs, el)
3783         {
3784           if (sRef_isCvar (el))
3785             {
3786               uentry current;
3787               int index = sRef_getScopeIndex (el);
3788               
3789               if (sRef_isFileStatic (el))
3790                 {
3791                   llassert (usymtab_isDefined (filetab));
3792                   current = usymtab_fetchIndex (filetab, index);
3793                 }
3794               else
3795                 {
3796                   current = usymtab_fetchIndex (globtab, index);
3797                 }
3798               
3799               if (uentry_isVariable (current))
3800                 {
3801                   uentry_fixupSref (current);
3802                 }
3803               else
3804                 {
3805                   sRef_clearDerived (uentry_getSref (current));
3806                 }
3807             }
3808         } end_globSet_allElements;
3809     }
3810   
3811   usymtab_quietExitScope (exprNode_loc (expr));
3812   
3813   if (lctab != usymtab_undefined)
3814     {
3815       /*@i@*/ lctab->env = utab;  
3816       /*@i@*/ utab = ctab;
3817     /*@-branchstate@*/ } /*@=branchstate@*/
3818 /*@-globstate@*/
3819 }
3820 /*@=globstate@*/
3821
3822 /*
3823 ** yikes!  don't let the '170 kids see this one...
3824 */
3825
3826 int
3827 uentry_directParamNo (uentry ue)
3828 {
3829   if (uentry_isVar (ue))
3830     {
3831       sRef sr = uentry_getSref (ue);
3832
3833       if (sRef_lexLevel (sr) == functionScope)
3834         {
3835           /*@access sRef@*/ /*@-null@*/
3836           int index = sr->info->cvar->index;
3837           /*@noaccess sRef@*/ /*@=null@*/
3838
3839           if (index < uentryList_size (context_getParams ()))
3840             {
3841               return index;
3842             }
3843         }
3844     }
3845   return -1;
3846 }
3847
3848 /*@dependent@*/ /*@exposed@*/ uentry
3849   usymtab_getParam (int paramno)
3850   /*@globals utab@*/
3851 {
3852   /*
3853   ** requires in a function context (checked)
3854   **
3855   ** depends on no nested functions --- the function
3856   ** parameters are ALWAYS one scope inside the global scope
3857   ** and entered in order!
3858   */
3859   usymtab s = utab;
3860
3861   if (!context_inFunctionLike ())
3862     llfatalbug (message ("usymtab_getParam: not in function context: %q", 
3863                          context_unparse ()));
3864
3865   while (s->lexlevel > paramsScope) 
3866     {
3867       s = s->env;
3868     }
3869
3870   llassert (usymtab_isDefined (s));
3871
3872   if (paramno >= s->nentries)
3873     {
3874       /*  
3875       ** Parse errors lead to this. 
3876       */
3877
3878       uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
3879                                            ctype_unknown);
3880       
3881       uentry_markOwned (err);
3882       return (err);
3883     }
3884
3885   return (s->entries[paramno]);
3886 }
3887
3888 static /*@dependent@*/ /*@exposed@*/ uentry 
3889 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
3890 {
3891   uentry ue;
3892
3893   
3894   ue = usymtab_getRefNoisy (u, level, index);
3895
3896   
3897   if (uentry_isUndefined (ue))
3898     {
3899       llbug (message ("usymtab_getRef: out of range: %d. level = %d",
3900                     index, level));
3901     }
3902
3903   
3904   return ue;
3905 }
3906
3907 static /*@dependent@*/ /*@exposed@*/ usymtab 
3908   usymtab_dropEnv (/*@notnull@*/ usymtab s)
3909 {
3910   if (s->kind == US_CBRANCH)
3911     {
3912       usymtab t = s;
3913
3914       do 
3915         {
3916           t = s;
3917           s = s->env;
3918           llassert (s != GLOBAL_ENV);
3919         } while (s->kind == US_CBRANCH); 
3920       /* drop all cases (except in nested scopes */ 
3921
3922       s = t;
3923       llassert (s != GLOBAL_ENV);
3924     }
3925
3926   if (s->kind == US_FBRANCH)
3927     {
3928       s = s->env; /* skip the true branch */
3929       llassert (usymtab_isDefined (s));
3930       llassert (s->kind == US_TBRANCH);
3931     }
3932
3933   llassert (s != GLOBAL_ENV);
3934   s = s->env;
3935
3936   return s;
3937 }
3938
3939 /*@dependent@*/ /*@exposed@*/ uentry
3940   usymtab_getRefQuiet (int level, usymId index)
3941   /*@globals utab@*/
3942 {
3943   usymtab s = utab;
3944   
3945   
3946   llassert (s != NULL);
3947   llassert (index >= 0);
3948
3949   if (level > s->lexlevel)
3950     {
3951             
3952       return uentry_undefined;
3953     }
3954
3955   llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d", 
3956                                         level, s->lexlevel)); 
3957
3958   while (s->lexlevel > level)
3959     {
3960       if (usymtab_isBranch (s))
3961         {
3962           int eindex = refTable_lookup (s, level, index);
3963
3964           if (eindex != NOT_FOUND)
3965             {
3966               return (s->entries[eindex]);
3967             }
3968         }
3969
3970       s = usymtab_dropEnv (s);
3971     }
3972
3973   while (usymtab_isBranch (s) && s->lexlevel == level)
3974     {
3975       int eindex = refTable_lookup (s, level, index);
3976       
3977       if (eindex != NOT_FOUND)
3978         {
3979           return (s->entries[eindex]);
3980         }
3981
3982       s = usymtab_dropEnv (s);
3983     }
3984  
3985   if (index >= s->nentries)
3986     {
3987       return uentry_undefined;
3988     }
3989
3990   llassert (!uentry_isUndefined (s->entries[index]));
3991
3992   return s->entries[index];
3993 }
3994
3995 static /*@dependent@*/ /*@exposed@*/ uentry
3996 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
3997 {
3998   usymtab otab = s;
3999   uentry ue = uentry_undefined;
4000
4001   
4002   llassert (index >= 0);
4003
4004   
4005   while (s->lexlevel > level)
4006     {
4007       
4008       if (usymtab_isBranch (s))
4009         {
4010           int eindex = refTable_lookup (s, level, index);
4011
4012           if (eindex != NOT_FOUND)
4013             {
4014               ue = s->entries[eindex];
4015
4016               if (s != otab)
4017                 {
4018                   while (!usymtab_isBranch (otab))
4019                     {
4020                       otab = usymtab_dropEnv (otab);
4021                       llassert (otab != GLOBAL_ENV);
4022                     }
4023                 
4024                   if (refTable_lookup (otab, level, index) == NOT_FOUND)
4025                     {
4026                       ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4027                     }
4028                   else
4029                     {
4030                       ;
4031                     }
4032                 }
4033               
4034               return ue;
4035             }
4036         }
4037
4038       s = usymtab_dropEnv (s);
4039     }
4040
4041   llassert (usymtab_isDefined (s));
4042
4043   while (usymtab_isBranch (s) && s->lexlevel == level)
4044     {
4045       int eindex = refTable_lookup (s, level, index);
4046
4047       
4048       if (eindex != NOT_FOUND)
4049         {
4050           ue = s->entries[eindex];
4051           
4052           if (s != otab)
4053             {
4054               while (!usymtab_isBranch (otab))
4055                 {
4056                   otab = usymtab_dropEnv (otab);
4057                   llassert (otab != GLOBAL_ENV);
4058                 }
4059
4060               ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4061             }
4062           else
4063             {
4064               ;
4065             } 
4066
4067           return ue;
4068         }
4069
4070       s = usymtab_dropEnv (s);
4071           }
4072
4073   if (s->lexlevel == level && (index < s->nentries))
4074     {
4075       ue = s->entries[index];
4076       
4077       if (uentry_isValid (ue))
4078         {
4079           if (s != otab)
4080             {
4081               while (!usymtab_isBranch (otab))
4082                 {
4083                   otab = usymtab_dropEnv (otab);
4084                   
4085                   if (otab == GLOBAL_ENV)
4086                     {
4087                       return ue;
4088                     }
4089                 }
4090               
4091               ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4092             }
4093           else
4094             {
4095                     }
4096         }
4097
4098       return ue;
4099     }
4100
4101   
4102   if (index >= s->nentries)
4103     {
4104       return uentry_undefined;
4105     }
4106
4107   llassert (!uentry_isUndefined (s->entries[index]));
4108
4109   return s->entries[index];
4110 }
4111
4112 /*
4113 ** looking up entries
4114 **
4115 ** If entry is inside a branch, then copy it, and put it into 
4116 ** the branch table.
4117 */
4118
4119 static
4120 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4121 {
4122   refTable rt = ut->reftable;
4123   int i;
4124
4125   llassert (rt != NULL);
4126
4127   
4128   for (i = 0; i < ut->nentries; i++)
4129     {
4130       if (rt[i]->level == level && rt[i]->index == index)
4131         {
4132                   return i;
4133         }
4134     }
4135
4136     return NOT_FOUND;
4137 }
4138   
4139 static
4140 /*@only@*/ refentry refentry_create (int level, int index)
4141 {
4142   refentry r = (refentry) dmalloc (sizeof (*r));
4143
4144   r->level = level;
4145   r->index = index;
4146
4147   return r;
4148 }
4149
4150 static /*@dependent@*/ /*@exposed@*/ uentry
4151 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4152 {
4153   int eindex;
4154   usymtab ut = s;
4155
4156   llassert (ut->reftable != NULL);
4157
4158   while (s != GLOBAL_ENV)
4159     {
4160       eindex = usymtab_getIndex (s, k);
4161       
4162       if (eindex != NOT_FOUND)
4163         {
4164           uentry current = s->entries[eindex];
4165
4166           if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4167             {
4168               uentry ue;
4169
4170               DPRINTF (("Here: copying %s", uentry_unparseFull (current)));
4171
4172               ue = uentry_copy (current);
4173
4174               DPRINTF (("Here: copying %s", uentry_unparseFull (ue)));
4175
4176               usymtab_addEntryQuiet (ut, ue);
4177
4178               if (s->reftable != NULL)
4179                 {
4180                   refentry ref = s->reftable[eindex];
4181
4182                   
4183                   ut->reftable[ut->nentries - 1] 
4184                     = refentry_create (ref->level, ref->index);
4185                 }
4186               else
4187                 {
4188                   ut->reftable[ut->nentries - 1] 
4189                     = refentry_create (s->lexlevel, eindex);
4190                 }
4191               
4192               return (ue);
4193             }
4194           else
4195             {
4196               return (current);
4197             }
4198         }
4199
4200       s = usymtab_dropEnv (s);
4201     }
4202
4203   return uentry_undefined;
4204 }
4205
4206 static uentry usymtab_lookupAux (usymtab s, cstring k)
4207 {
4208   DPRINTF (("Lookup: %s", k));
4209
4210   while (s != GLOBAL_ENV)
4211     {
4212       int eindex = usymtab_getIndex (s, k);
4213
4214       if (eindex != NOT_FOUND)
4215         {
4216           uentry ret = s->entries[eindex];
4217           
4218           DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4219           return (ret);
4220         }
4221
4222       if (s->kind == US_TBRANCH || s->kind == US_FBRANCH 
4223           || s->kind == US_CBRANCH)
4224         {
4225           uentry ret = usymtab_addRefEntry (s, k);
4226           DPRINTF (("Ref entry: %s", uentry_unparseFull (ret)));
4227           return ret;
4228         }
4229       
4230       s = s->env;
4231     }
4232   
4233   return uentry_undefined;
4234 }
4235
4236 static /*@dependent@*/ /*@exposed@*/ uentry
4237 usymtab_lookupQuiet (usymtab s, cstring k)
4238 {
4239   int eindex;
4240
4241   while (s != GLOBAL_ENV)
4242     {
4243       eindex = usymtab_getIndex (s, k);
4244       
4245       if (eindex != NOT_FOUND)
4246         {
4247           uentry ret = s->entries[eindex];
4248           return (ret);
4249         }
4250       
4251       s = s->env;
4252     }
4253
4254   return uentry_undefined;
4255 }
4256
4257 /*@dependent@*/ /*@observer@*/ uentry
4258   usymtab_lookupSafe (cstring k)
4259   /*@globals utab@*/
4260 {
4261   DPRINTF (("Lookup safe: %s", k));
4262   return (usymtab_lookupAux (utab, k));
4263 }
4264
4265 uentry
4266   usymtab_lookupExpose (cstring k)
4267   /*@globals utab@*/
4268 {
4269   uentry ce = usymtab_lookupAux (utab, k);
4270
4271   if (uentry_isUndefined (ce))
4272     {
4273       llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
4274     }
4275
4276   if (uentry_isPriv (ce))
4277     {
4278       llfatalbug (message ("usymtab_lookup: private: *%s*", k));
4279     }
4280
4281   return ce;
4282 }
4283
4284 uentry usymtab_lookupExposeGlob (cstring k)
4285 {
4286   return (usymtab_lookupGlobSafe (k));
4287 }
4288
4289 uentry usymtab_lookupGlob (cstring k)
4290   /*@globals globtab@*/
4291 {
4292   uentry ce = usymtab_lookupAux (globtab, k);
4293
4294   if (uentry_isUndefined (ce))
4295     llfatalbug (message ("usymtab_lookup: not found: %s", k));
4296
4297   if (uentry_isPriv (ce))
4298     llfatalbug (message ("usymtab_lookup: private: %s", k));
4299
4300   return ce;
4301 }
4302
4303 /*@observer@*/ uentry
4304   usymtab_lookupGlobSafe (cstring k)
4305   /*@globals globtab@*/
4306 {
4307   uentry ce = usymtab_lookupAux (globtab, k);
4308
4309   return ce;
4310 }
4311
4312 uentry usymtab_lookupEither (cstring k)
4313    /*@globals utab@*/
4314 {
4315   uentry ce = usymtab_lookupSafe (k);
4316
4317   if (uentry_isUndefined (ce))
4318     llfatalerror (message ("usymtab_lookup: not found: %s", k));
4319
4320   return ce;
4321 }
4322
4323 # ifndef NOLCL
4324 ctype
4325 usymtab_lookupType (cstring k)
4326    /*@globals globtab@*/
4327 {
4328   usymId uid = usymtab_getTypeId (k);
4329
4330   if (uid == USYMIDINVALID)
4331     {
4332       llcontbug (message ("usymtab_lookupType: not found: %s", k));
4333       return ctype_unknown;
4334     }
4335   
4336   return (uentry_getRealType (usymtab_getTypeEntry (uid)));
4337 }
4338 # endif
4339
4340 ctype
4341 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
4342 {
4343   usymId uid = usymtab_getTypeId (k);
4344
4345   if (uid == USYMIDINVALID)
4346     {
4347       llcontbug (message ("usymtab_lookupType: not found: %s", k));
4348       return ctype_unknown; 
4349     }
4350   
4351   return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
4352 }
4353   
4354 /*
4355 ** if there is an unnamed lcl-specified struct tag matching
4356 ** the uentryList, return its datatype.  Otherwise, returns
4357 ** ctype_undefined.
4358 */
4359
4360 ctype
4361 usymtab_structFieldsType (uentryList f)
4362    /*@globals globtab@*/
4363 {
4364   return (usymtab_suFieldsType (f, TRUE));
4365 }
4366
4367 ctype
4368 usymtab_unionFieldsType (uentryList f)
4369    /*@globals globtab@*/
4370 {
4371   return (usymtab_suFieldsType (f, FALSE));
4372 }
4373
4374 static ctype
4375 usymtab_suFieldsType (uentryList f, bool isStruct)
4376   /*@globals globtab@*/
4377 {
4378   int i;
4379
4380   if (fileloc_isSpec (g_currentloc)) return (ctype_undefined);
4381
4382   for (i = 0; i < globtab->nentries; i++)
4383     {
4384       uentry current = globtab->entries[i];
4385
4386       if ((isStruct 
4387            ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
4388         {
4389           if (isFakeTag (uentry_rawName (current)))
4390             {
4391               ctype ct = uentry_getType (current);
4392
4393               if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
4394                   && (uentryList_matchFields (f, ctype_getFields (ct))))
4395                 {
4396                                   return uentry_getAbstractType (current);
4397                 }
4398             }
4399         }
4400     }
4401   
4402     return ctype_undefined;
4403 }
4404
4405 ctype
4406   usymtab_enumEnumNameListType (enumNameList f)
4407   /*@globals globtab@*/
4408 {
4409   int i;
4410
4411   for (i = 0; i < globtab->nentries; i++)
4412     {
4413       uentry current = globtab->entries[i];
4414
4415       if (uentry_isEnumTag (current))
4416         {
4417           if (isFakeTag (uentry_rawName (current)))
4418             {
4419               ctype ct = uentry_getType (current);
4420
4421               if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
4422                 {
4423                   return uentry_getType (current);
4424                 }
4425             }
4426         }
4427     }
4428   
4429   return ctype_undefined;
4430 }
4431
4432 bool
4433 usymtab_exists (cstring k)
4434    /*@globals utab@*/
4435 {
4436   uentry ce = usymtab_lookupSafe (k);
4437
4438   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4439 }
4440
4441 bool
4442 usymtab_existsReal (cstring k)
4443    /*@globals utab@*/
4444 {
4445   uentry ce = usymtab_lookupSafe (k);
4446
4447   return (!(uentry_isUndefined (ce)) 
4448           && !(uentry_isPriv (ce))
4449           && !(uentry_isExpandedMacro (ce)));
4450 }
4451
4452 bool
4453   usymtab_existsGlob (cstring k)
4454   /*@globals globtab@*/
4455 {
4456   uentry ce = usymtab_lookupAux (globtab, k);
4457
4458   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4459 }
4460
4461 # ifndef NOLCL
4462 bool
4463 usymtab_existsEither (cstring k)
4464   /*@globals utab@*/
4465 {
4466   uentry ce = usymtab_lookupAux (utab, k);
4467   
4468   return (uentry_isValid (ce));
4469 }
4470
4471 bool
4472   usymtab_existsGlobEither (cstring k)
4473   /*@globals globtab@*/
4474 {
4475   uentry ce = usymtab_lookupAux (globtab, k);
4476   
4477   return (uentry_isValid (ce));
4478 }
4479 # endif
4480
4481 bool
4482 usymtab_existsType (cstring k)
4483   /*@globals globtab@*/
4484 {
4485   uentry ce = usymtab_lookupAux (globtab, k);
4486
4487   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
4488 }
4489
4490 bool
4491 usymtab_existsTypeEither (cstring k)
4492   /*@globals globtab@*/
4493 {
4494   uentry ce = usymtab_lookupAux (globtab, k);
4495
4496     return (uentry_isValid (ce) && uentry_isDatatype (ce));
4497 }
4498
4499 bool
4500 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
4501 {
4502   cstring sname = makeStruct (k);
4503   uentry ce = usymtab_lookupAux (globtab, sname);
4504
4505   cstring_free (sname);
4506
4507   
4508   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4509 }
4510
4511 bool
4512 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
4513 {
4514   cstring uname = makeUnion (k);
4515   uentry ce = usymtab_lookupAux (globtab, uname);
4516
4517   cstring_free (uname);
4518
4519   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4520 }
4521
4522 bool
4523 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
4524 {
4525   cstring ename = makeEnum (k);
4526   uentry ce = usymtab_lookupAux (globtab, ename);
4527
4528   cstring_free (ename);
4529   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4530 }
4531
4532 # ifndef NOLCL
4533 bool usymtab_existsVar (cstring k)
4534    /*@globals utab@*/
4535 {
4536   uentry ce = usymtab_lookupSafe (k);
4537
4538   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
4539 }
4540 # endif
4541
4542 /*
4543 ** destructors
4544 */
4545
4546 static void
4547 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
4548 {
4549   if (x != NULL)
4550     {
4551       int i;
4552
4553       for (i = 0; i < nentries; i++)
4554         {
4555           sfree (x[i]);
4556         }
4557       
4558       sfree (x);
4559     }
4560 }
4561   
4562 static void
4563 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
4564   /*@globals globtab, utab, filetab@*/
4565 {
4566   int i;
4567
4568   aliasTable_free (u->aliases);
4569   environmentTable_free (u->environment);
4570   refTable_free (u->reftable, u->nentries);
4571
4572   if (u == filetab || u == globtab)
4573     {
4574       for (i = 0; i < u->nentries; i++)
4575         {
4576           uentry_freeComplete (u->entries[i]);
4577         }
4578     }
4579   else
4580     {
4581       for (i = 0; i < u->nentries; i++)
4582         {
4583           uentry_free (u->entries[i]);
4584         }
4585     }
4586
4587   guardSet_free (u->guards);
4588   sfree (u->entries);
4589
4590   if (u != globtab 
4591       && u != utab
4592       && u != filetab)
4593     {
4594       llassert (u->htable == NULL);
4595       sfree (u);
4596     }
4597
4598 /*@-mustfree@*/
4599 } /*@=mustfree@*/
4600
4601 static void
4602 usymtab_freeAux (/*@only@*/ usymtab u)
4603    /*@globals globtab, utab, filetab@*/
4604    /*@modifies u@*/
4605 {
4606   while (u != GLOBAL_ENV)
4607     {
4608       usymtab t = u->env;
4609       usymtab_freeLevel (u);
4610       u = t;
4611       /*@-branchstate@*/ 
4612     } 
4613   /*@=branchstate@*/
4614 }
4615
4616 void usymtab_free () 
4617   /*@globals killed utab, globtab, filetab@*/ 
4618   /*@modifies utab@*/
4619 {
4620   dbgfree = TRUE;
4621   usymtab_freeAux (utab);
4622 }
4623
4624 static int usymtab_lexicalLevel (void) /*@globals utab@*/
4625 {
4626   return (utab->lexlevel);
4627 }
4628
4629 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
4630 {
4631   return (utab == globtab);
4632 }
4633
4634 bool usymtab_inFileScope () /*@globals utab@*/
4635 {
4636   return (utab->lexlevel == fileScope);
4637 }
4638
4639 bool usymtab_inFunctionScope () /*@globals utab@*/
4640 {
4641   return (utab->lexlevel == functionScope);
4642 }
4643
4644 # ifndef NOLCL
4645 void
4646 usymtab_replaceEntry (uentry s)
4647   /*@globals utab, globtab@*/
4648   /*@modifies utab, s@*/
4649 {
4650   usymtab_replaceEntryAux (utab, s);
4651 }
4652 # endif
4653
4654 bool
4655 usymtab_matchForwardStruct (usymId u1, usymId u2)
4656    /*@globals globtab@*/
4657 {
4658   uentry ue1 = usymtab_getTypeEntry (u1);
4659   uentry ue2 = usymtab_getTypeEntry (u2);
4660
4661   if (uentry_isAnyTag (ue2))
4662     {
4663       ctype reptype = uentry_getType (ue1);
4664       
4665       if (ctype_isPointer (reptype))
4666         {
4667           ctype repbase = ctype_getBaseType (reptype);
4668   
4669           if (ctype_isUA (repbase))
4670             {
4671               typeId rtuid = ctype_typeId (repbase);
4672
4673               if (u2 == rtuid) return TRUE;
4674               
4675               if (usymId_isValid (rtuid))
4676                 {
4677                   reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
4678                   
4679                   return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
4680                 }
4681             }
4682         }
4683     }
4684   
4685   return FALSE;
4686 }
4687
4688 void usymtab_addGuards (guardSet guards)
4689   /*@modifies utab@*/
4690 {
4691   utab->guards = guardSet_union (utab->guards, guards);
4692   }
4693
4694 static bool usymtab_isGuardedAux (sRef s)
4695   /*@globals utab@*/
4696 {
4697   usymtab tab = utab;
4698   sRef base = sRef_getRootBase (s);
4699   int lowlevel = paramsScope;
4700   int baselevel = sRef_lexLevel (base);
4701
4702   if (sRef_isCvar (base))
4703     {
4704       lowlevel = baselevel;
4705       if (lowlevel < paramsScope) lowlevel = paramsScope;
4706     }
4707   
4708   while (tab->lexlevel >= lowlevel)
4709     {
4710       if (guardSet_isGuarded (tab->guards, s))
4711         {
4712           /*
4713           if (!sRef_definitelyNull (s))
4714             {
4715               sRef_setNotNull (s, fileloc_undefined);
4716             }
4717             */
4718           return TRUE;
4719         }
4720
4721       tab = usymtab_dropEnv (tab);
4722     }
4723   
4724   return FALSE;
4725 }
4726
4727 void usymtab_unguard (sRef s) /*@modifies utab@*/
4728 {
4729   usymtab tab = utab;
4730   sRef base = sRef_getRootBase (s);
4731   int lowlevel = paramsScope;
4732   int baselevel = sRef_lexLevel (base);
4733   
4734   if (sRef_isCvar (base))
4735     {
4736       lowlevel = baselevel;
4737       if (lowlevel < paramsScope) lowlevel = paramsScope;
4738     }
4739
4740   while (tab->lexlevel >= lowlevel)
4741     {
4742       if (guardSet_isGuarded (tab->guards, s))
4743         {
4744           guardSet_delete (tab->guards, s);
4745         }
4746       
4747       tab = usymtab_dropEnv (tab);
4748     }
4749 }
4750
4751 bool usymtab_isGuarded (sRef s)
4752 {
4753   
4754   return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
4755 }
4756
4757 bool usymtab_isProbableNull (sRef s)
4758 {
4759   return (sRef_aliasCheckSimplePred (usymtab_isProbableNullAux, s));
4760 }
4761
4762 bool usymtab_isProbableDeepNull (sRef s)
4763 {
4764   return (sRef_deepPred (usymtab_isProbableNull, s));
4765 }
4766
4767 static bool usymtab_isProbableNullAux (sRef s)
4768   /*@globals utab@*/
4769 {
4770   usymtab tab = utab;
4771   sRef base = sRef_getRootBase (s);
4772   int  lowlevel = paramsScope;
4773   
4774   if (sRef_isCvar (base))
4775     {
4776       lowlevel = sRef_lexLevel (base);
4777       if (lowlevel < paramsScope) lowlevel = paramsScope;
4778     }
4779   
4780   while (tab->lexlevel >= lowlevel)
4781     {
4782       if (guardSet_isProbableNull (tab->guards, s))
4783         {
4784           return TRUE;
4785         }
4786       
4787       while (tab->kind == US_CBRANCH) 
4788         {
4789           tab = tab->env;
4790         }
4791
4792       llassert (usymtab_isDefined (tab));
4793
4794       if (tab->kind == US_FBRANCH)
4795         {
4796           tab = tab->env;
4797           llassert (tab->kind == US_TBRANCH);
4798         }
4799       
4800       tab = tab->env;
4801     }
4802
4803   return FALSE;
4804 }
4805
4806 void
4807 usymtab_printGuards ()
4808   /*@globals utab, globtab@*/
4809 {
4810   usymtab ttab = utab;
4811
4812   while (ttab != globtab)
4813     {
4814       llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
4815                       guardSet_unparse (ttab->guards)));
4816       ttab = ttab->env;
4817     }
4818 }
4819
4820 void
4821 usymtab_displayAllUses ()
4822   /*@globals utab, globtab@*/
4823 {
4824   usymtab copy;
4825
4826   /* only in top scope */
4827   llassert (utab == globtab);
4828
4829   /* need a copy, so order is not messed up by sort! */  
4830   copy = usymtab_shallowCopy (globtab); 
4831   
4832   qsort (copy->entries, (size_t)copy->nentries, 
4833          sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
4834
4835   usymtab_entries (copy, ue)
4836     {
4837       if (uentry_isValid (ue))
4838         {
4839           filelocList uses = uentry_getUses (ue);
4840           int size = filelocList_realSize (uses);
4841
4842           if (fileloc_isDefined (uentry_whereDefined (ue)) 
4843               && !fileloc_isLib (uentry_whereDefined (ue))
4844               && (size > 0))
4845             {
4846               llmsg (message ("%q (%q), %d use%p:\n   %q", 
4847                               uentry_getName (ue),
4848                               fileloc_unparse (uentry_whereDefined (ue)),
4849                               size, filelocList_unparseUses (uses)));
4850             }
4851         }
4852     } end_usymtab_entries;
4853   
4854   usymtab_shallowFree (copy);
4855 }
4856
4857 static /*@dependent@*/ /*@exposed@*/ usymtab
4858 usymtab_getFileTab ()
4859   /*@globals filetab@*/
4860 {
4861   llassert (filetab != NULL);
4862
4863   return filetab;
4864 }
4865
4866 /*@only@*/ cstring
4867 usymtab_unparseStack ()
4868   /*@globals utab@*/
4869 {
4870   return (usymtab_unparseStackTab (utab));
4871 }
4872  
4873 static /*@only@*/ cstring
4874 usymtab_unparseStackTab (usymtab t)
4875 {
4876   bool firstOne = TRUE;
4877   cstring ret = cstring_makeLiteral ("[");
4878
4879   while (t != GLOBAL_ENV)
4880     {
4881       if (firstOne)
4882         {
4883           ret = message ("%q %q", ret, usymtab_typeName (t));
4884           firstOne = FALSE;
4885         }
4886       else
4887         {
4888           ret = message ("%q, %q", ret, usymtab_typeName (t));
4889         }
4890       t = t->env;
4891     }
4892
4893   ret = message ("%q ]", ret);
4894   return ret;
4895 }
4896
4897 static /*@only@*/ cstring
4898 usymtab_typeName (/*@notnull@*/ usymtab t)
4899 {
4900   switch (t->kind)
4901     {
4902     case US_GLOBAL:  return cstring_makeLiteral ("global");
4903     case US_NORMAL:  return cstring_makeLiteral ("normal");
4904     case US_TBRANCH: return cstring_makeLiteral ("true");
4905     case US_FBRANCH: return cstring_makeLiteral ("false");
4906     case US_CBRANCH: return cstring_makeLiteral ("case");
4907     case US_SWITCH:  return cstring_makeLiteral ("switch");
4908     }
4909   
4910   BADEXIT;
4911 }
4912
4913 void usymtab_testInRange (sRef s, int index) /*@globals utab;@*/
4914 {
4915   /*@i22*/
4916   /*@-globs*/
4917   environmentTable_testInRange (utab->environment, s, index);
4918   /*@=globs*/
4919 }
4920 void usymtab_postopVar (sRef sr) /*@globals utab;@*/
4921 {
4922   environmentTable_postOpvar (utab->environment, sr);
4923   
4924 }
4925 /* doesn't do much check here assumes checking is done before call*/
4926 void usymtab_addExactValue(sRef s1, int val)
4927 {
4928   /*@i22@*/ utab->environment = environmentTable_addExactValue (utab->environment, s1, val);
4929 }
4930   
4931 void usymtab_addMustAlias (sRef s, sRef al)
4932   /*@modifies utab@*/
4933 {
4934   if (sRef_isMeaningful (s) && sRef_isMeaningful (al)
4935       && !(sRef_isConst (s) || sRef_isConst (al))
4936       && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al)))
4937       && !(sRef_similar (s, al)))
4938     {
4939       utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al); 
4940       DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
4941
4942       /*
4943       ** for local variable, aliasing is symmetric 
4944       */
4945       
4946       if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
4947         {
4948           utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s); 
4949         }
4950     }
4951   else
4952     {
4953       ;
4954     }
4955 }
4956
4957 /*
4958 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
4959 */
4960
4961 void usymtab_addForceMustAlias (sRef s, sRef al)
4962   /*@modifies utab@*/
4963 {
4964   if (sRef_isMeaningful (s) 
4965       && sRef_isMeaningful (al)
4966       && !(sRef_isConst (s) || sRef_isConst (al))
4967       && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
4968     {
4969       utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al); 
4970       DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
4971
4972       /*
4973       ** for local variable, aliasing is symmetric 
4974       */
4975       
4976       if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
4977         {
4978           utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s); 
4979         }
4980     }
4981   else
4982     {
4983       ;
4984     }
4985 }
4986
4987 void usymtab_clearAlias (sRef s)
4988   /*@modifies utab, s@*/
4989 {
4990   
4991   aliasTable_clearAliases (utab->aliases, s); 
4992 }
4993
4994 sRefSet usymtab_allAliases (sRef s)
4995    /*@globals utab@*/  
4996 {
4997   if (sRef_isMeaningful (s))
4998     {
4999       sRefSet ret;
5000
5001             
5002       ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5003                                aliasTable_canAlias (utab->aliases, s));
5004             return (ret);
5005     }
5006   else
5007     {
5008       return sRefSet_undefined;
5009     }
5010 }
5011
5012 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5013   /*@globals utab@*/
5014 {
5015   if (sRef_isMeaningful (s))
5016     {
5017       sRefSet res = aliasTable_canAlias (utab->aliases, s);
5018
5019       return res;
5020     }
5021
5022   return sRefSet_undefined;
5023 }
5024
5025 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5026   /*@globals utab@*/
5027 {
5028   return (aliasTable_aliasedBy (utab->aliases, s));
5029 }
5030
5031 /*@only@*/ cstring usymtab_unparseAliases ()
5032   /*@globals utab@*/
5033 {
5034   return (aliasTable_unparse (utab->aliases));
5035 }
5036
5037 /*
5038 ** Debugging routines:
5039 **    okay to leak storage here, only for debugging 
5040 */
5041
5042 /*@-mustfree@*/ 
5043
5044 void
5045 usymtab_printOut (void)
5046   /*@globals utab@*/
5047 {
5048   int i;
5049   usymtab s = utab;
5050   int depth = 0;
5051   char *ind = mstring_copy ("               ");
5052
5053   fprintf (g_msgstream, "<<< [symbol table] >>>\n");
5054   
5055   while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5056     {
5057       cstring tname = usymtab_typeName (s);
5058
5059       if (depth < 5)
5060         {
5061           ind[depth * 3 + 1] = '\0';
5062         }
5063      
5064       fprintf (g_msgstream, "level: %d (%s)\n", s->lexlevel,
5065                cstring_toCharsSafe (tname));
5066
5067       cstring_free (tname);
5068
5069       for (i = 0; i < s->nentries; i++)
5070         {
5071           cstring us = uentry_unparseFull (s->entries[i]);
5072           fprintf (g_msgstream, "%s\n", cstring_toCharsSafe (us));
5073           cstring_free (us);
5074         }
5075       
5076       if (s->reftable != NULL && s->nentries > 0)
5077         {
5078           fprintf (g_msgstream, "\t<< Ref table >>\n");
5079
5080           for (i = 0; i < s->nentries; i++)
5081             {
5082               fprintf (g_msgstream, "\t%s %3d: %d, %d\n", ind, i, 
5083                        s->reftable[i]->level,
5084                        s->reftable[i]->index);
5085             }
5086         }
5087
5088       ind[depth * 3 + 1] = ' ';
5089       depth++;
5090       s = s->env;
5091     }
5092   fprintf (g_msgstream, "<<< end usymtab >>>\n");
5093   mstring_free (ind);
5094   return;
5095 }
5096
5097 void
5098 usymtab_printTypes ()
5099   /*@globals globtab@*/
5100 {
5101   usymtab_printAllAux (globtab);
5102 }
5103
5104 void 
5105 usymtab_printAll (void)
5106   /*@globals utab@*/
5107 {
5108   usymtab_printAllAux (utab);
5109 }
5110
5111 static void
5112 usymtab_printAllAux (usymtab s)
5113    /*@modifies g_msgstream@*/
5114 {
5115   int i;
5116   int depth = 0;
5117   char *ind = mstring_copy ("               ");
5118
5119   printf ("[[[ usymtab ]]]");
5120
5121   while (s != GLOBAL_ENV)
5122     {
5123       if (depth < 5)
5124         ind[depth * 3 + 1] = '\0';
5125       
5126       if (s->env == GLOBAL_ENV)
5127         {
5128           int looplow;
5129
5130           printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5131                   cstring_toCharsSafe (bool_unparse (s->mustBreak)), 
5132                   cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5133
5134           looplow = 0;
5135
5136           for (i = looplow; i < s->nentries; i++)
5137             {
5138               printf ("%s%3d. %s\n", ind, i, 
5139                       cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5140             }
5141         }
5142       else
5143         {
5144           printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5145                   cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5146                   cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5147
5148           for (i = 0; i < s->nentries; i++)
5149             {
5150               printf ("%s%3d %s\n", ind, i, 
5151                      cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5152             }
5153         }
5154       
5155       ind[depth * 3 + 1] = ' ';
5156       depth++;
5157       s = s->env;
5158     }
5159   printf ("----------\n");
5160 }
5161
5162 void
5163 usymtab_printComplete ()
5164   /*@globals utab@*/
5165 {
5166   int i;
5167   int depth = 0;
5168   char *ind = mstring_copy ("               ");
5169   usymtab s = utab;
5170
5171   while (s != GLOBAL_ENV)
5172     {
5173       if (depth < 5)
5174         {
5175           ind[depth * 3 + 1] = '\0';
5176         }
5177       
5178       if (s->env == GLOBAL_ENV)
5179         {
5180           int looplow;
5181
5182           printf ("level: %d\n", s->lexlevel);
5183
5184           looplow = 0;
5185
5186           for (i = looplow; i < s->nentries; i++)
5187             {
5188               printf ("%s%3d %s\n", ind, i, 
5189                       cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5190             }
5191         }
5192       else
5193         {
5194           printf ("level: %d\n", s->lexlevel);
5195           for (i = 0; i < s->nentries; i++)
5196             {
5197               printf ("%s%3d %s\n", ind, i, 
5198                      cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5199             }
5200         }
5201       
5202       ind[depth * 3 + 1] = ' ';
5203       depth++;
5204       s = s->env;
5205     }
5206
5207   printf ("----------\n");
5208   mstring_free (ind);
5209 }
5210
5211 static /*@only@*/ cstring /*@unused@*/ 
5212 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5213 {
5214   cstring c = message ("lexlevel: %d\n", s->lexlevel);
5215   int i;
5216
5217   for (i = 0; i < s->nentries; i++)
5218     {
5219       c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5220     }
5221
5222   c = message ("%q\n=========", c);
5223   return (c);
5224 }
5225
5226 static cstring /*@unused@*/ /*@only@*/ 
5227 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5228 {
5229   cstring c = message ("[%d/%s/%s] ", s->lexlevel, 
5230                        bool_unparse (s->mustBreak), 
5231                        exitkind_unparse (s->exitCode));
5232   int i;
5233
5234   for (i = 0; i < s->nentries; i++)
5235     {
5236       sRef sr = uentry_getSref (s->entries[i]);
5237
5238       if (i == 0)
5239         {
5240           c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]), 
5241                        sRef_isStateDefined (sr));
5242         }
5243       else
5244         {
5245           c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]), 
5246                        sRef_isStateDefined (sr));
5247         }
5248
5249     }
5250
5251   return (c);
5252 }
5253
5254 void
5255 usymtab_printLocal (void)
5256   /*@globals utab@*/
5257 {
5258   int i;
5259   usymtab s = utab;
5260
5261   printf ("lexlevel: %d\n", s->lexlevel);
5262
5263   for (i = 0; i < s->nentries; i++)
5264     {
5265       printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5266     }
5267   
5268   while (s->lexlevel > 1)
5269     {
5270       s = s->env;
5271     }
5272
5273   llassert (usymtab_isDefined (s));
5274
5275   printf ("Params:\n");
5276
5277   for (i = 0; i < s->nentries; i++)
5278     {
5279       printf ("%d: %s\n", i, 
5280               cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5281     }
5282 }
5283 /*@=mustfree@*/
5284
5285 static bool checkDistinctExternalName (uentry e)
5286   /*@globals globtab@*/
5287   /*@modifies *g_msgstream@*/
5288 {
5289   int checklen = context_getValue (FLG_EXTERNALNAMELEN);
5290   bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
5291   bool gotone = FALSE;
5292   bool extras = FALSE;
5293   bool hasError = FALSE;
5294   cstring name = uentry_rawName (e);
5295   usymtab st = globtab;
5296
5297   if (checklen == 0)
5298     {
5299       ;
5300     }
5301   else
5302     {
5303       if (uentry_isAnyTag (e)) 
5304         {
5305           checklen++;  /* the tag marker doesn't count */
5306         }
5307     }
5308
5309   usymtab_entries (st, oe)
5310     {
5311       if (uentry_sameObject (oe, e))
5312         {
5313           continue;
5314         }
5315
5316       if (checklen == 0)
5317         {
5318           if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
5319             {
5320               if (gotone)
5321                 {
5322                   extras = TRUE;
5323                   break;
5324                 }
5325               
5326               if (optgenerror 
5327                   (FLG_DISTINCTEXTERNALNAMES,
5328                    message 
5329                    ("External identifier %q is not distinguishable from %q "
5330                     "because alphabetical case is ignored",
5331                     uentry_getName (e),
5332                     uentry_getName (oe)),
5333                    uentry_whereLast (e)))
5334                 {
5335                   uentry_showWhereAny (oe);
5336                   uentry_setHasNameError (oe);
5337                   gotone = TRUE;
5338                 }
5339             }
5340         }
5341       else
5342         {
5343           if (ignorecase)
5344             {
5345               if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
5346                                                    name, checklen))
5347                 {
5348                   if (gotone)
5349                     {
5350                       extras = TRUE;
5351                       break;
5352                     }
5353                   
5354                   if (cstring_equalLen (uentry_rawName (oe), name, checklen))
5355                     {
5356                       if (optgenerror 
5357                           (FLG_DISTINCTEXTERNALNAMES,
5358                            /*@-sefparams@*/
5359                            message 
5360                            ("External identifier %q is not distinguishable from %q "
5361                             "in the first %d characters (%q)",
5362                             uentry_getName (e),
5363                             uentry_getName (oe),
5364                             checklen,
5365                             cstring_clip (uentry_getName (e), checklen)),
5366                            /*@=sefparams@*/
5367                            uentry_whereLast (e)))
5368                         {
5369                           uentry_showWhereAny (oe);
5370                           uentry_setHasNameError (oe);
5371                           gotone = TRUE;
5372                         }
5373                     }
5374                   else
5375                     {
5376                       if (gotone)
5377                         {
5378                           extras = TRUE;
5379                           break;
5380                         }
5381                       
5382                       if (optgenerror 
5383                           (FLG_DISTINCTEXTERNALNAMES,
5384                            message 
5385                            ("External identifier %q is not distinguishable from %q "
5386                             "in the first %d characters because alphabetical case "
5387                             "is ignored",
5388                             uentry_getName (e),
5389                             uentry_getName (oe),
5390                             checklen),
5391                            uentry_whereLast (e)))
5392                         {
5393                           uentry_showWhereAny (oe);
5394                           uentry_setHasNameError (oe);
5395                           gotone = TRUE;
5396                         }
5397                     }
5398                 }
5399             }
5400           else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
5401             {
5402               if (gotone)
5403                 {
5404                   extras = TRUE;
5405                   break;
5406                 }
5407               
5408               if (optgenerror 
5409                   (FLG_DISTINCTEXTERNALNAMES,
5410                    /*@-sefparams@*/
5411                    message 
5412                    ("External identifier %q is not distinguishable from %q "
5413                     "in the first %d characters (%q)",
5414                     uentry_getName (e),
5415                     uentry_getName (oe),
5416                     checklen,
5417                     cstring_clip (uentry_getName (e), checklen)),
5418                    /*@=sefparams@*/
5419                    uentry_whereLast (e)))
5420                 {
5421                   uentry_showWhereAny (oe);
5422                   uentry_setHasNameError (oe);
5423                   gotone = TRUE;
5424                 }
5425             }
5426           else
5427             {
5428               ; /* okay */
5429             }
5430         }
5431     } end_usymtab_entries ;
5432
5433   hasError = gotone;
5434   
5435   if (extras)
5436     {
5437       llgenindentmsgnoloc
5438         (cstring_makeLiteral ("One or more additional "
5439                               "indistinguishable external "
5440                               "names not reported"));
5441     }
5442
5443   return hasError;
5444 }
5445
5446 static bool checkDistinctInternalName (uentry e)
5447   /*@globals utab@*/
5448   /*@modifies *g_msgstream@*/
5449 {
5450   usymtab ttab = utab;
5451   cstring name = uentry_rawName (e);
5452   int numchars = context_getValue (FLG_INTERNALNAMELEN);
5453   bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
5454   bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
5455
5456   if (uentry_isAnyTag (e) && (numchars != 0))
5457     {
5458       numchars++;  /* the tag marker doesn't count */
5459     }
5460   
5461   while (usymtab_isDefined (ttab))
5462     {
5463       usymtab_entries (ttab, oe)
5464         {
5465           if (uentry_sameObject (oe, e))
5466             {
5467               /*@innercontinue@*/ continue;
5468             }
5469
5470           switch (cstring_genericEqual
5471                   (name, uentry_rawName (oe),
5472                    numchars, caseinsensitive, lookalike))
5473             {
5474             case CGE_DISTINCT: /* okay */
5475               /*@switchbreak@*/ 
5476               break;
5477             case CGE_SAME:
5478               if (cstring_equal (name, uentry_rawName (oe)))
5479                 {
5480                   ; /* got a shadow error */
5481                 }
5482               else
5483                 {
5484                   if (optgenerror 
5485                       (FLG_DISTINCTINTERNALNAMES,
5486                        /*@-sefparams@*/
5487                        message 
5488                        ("Internal identifier %q is not distinguishable from %q "
5489                         "in the first %d characters (%q)",
5490                         uentry_getName (e),
5491                         uentry_getName (oe),
5492                         numchars,
5493                         cstring_clip (uentry_getName (e), numchars)),
5494                        /*@=sefparams@*/
5495                        uentry_whereLast (e)))
5496                     {
5497                       uentry_showWhereAny (oe);
5498                       uentry_setHasNameError (oe);
5499                       return TRUE;
5500                     }
5501                 }
5502               /*@switchbreak@*/
5503               break;
5504             case CGE_CASE:
5505               if (numchars == 0 
5506                   || (cstring_length (name) <= numchars))
5507                 {
5508                   if (optgenerror 
5509                       (FLG_DISTINCTINTERNALNAMES,
5510                        message 
5511                        ("Internal identifier %q is not distinguishable from %q "
5512                         "without case sensitivity",
5513                         uentry_getName (e),
5514                         uentry_getName (oe)),
5515                        uentry_whereLast (e)))
5516                     {
5517                       uentry_showWhereAny (oe);
5518                       uentry_setHasNameError (oe);
5519                       return TRUE;
5520                     }
5521                 }
5522               else 
5523                 {
5524                   if (optgenerror 
5525                       (FLG_DISTINCTINTERNALNAMES,
5526                        message 
5527                        ("Internal identifier %q is not distinguishable from %q "
5528                         "in the first %d characters without case sensitivity",
5529                         uentry_getName (e),
5530                         uentry_getName (oe),
5531                         numchars),
5532                        uentry_whereLast (e)))
5533                     {
5534                       uentry_showWhereAny (oe);
5535                       uentry_setHasNameError (oe);
5536                       return TRUE;
5537                     }
5538                 }
5539               /*@switchbreak@*/ 
5540               break;
5541             case CGE_LOOKALIKE:
5542               if (numchars == 0 
5543                   || (cstring_length (name) <= numchars))
5544                 {
5545                   if (optgenerror 
5546                       (FLG_DISTINCTINTERNALNAMES,
5547                        message 
5548                        ("Internal identifier %q is not distinguishable from %q "
5549                         "except by lookalike characters",
5550                         uentry_getName (e),
5551                         uentry_getName (oe)),
5552                        uentry_whereLast (e)))
5553                     {
5554                       uentry_showWhereAny (oe);
5555                       uentry_setHasNameError (oe);
5556                       return TRUE;
5557                     }
5558                 }
5559               else 
5560                 {
5561                   if (optgenerror 
5562                       (FLG_DISTINCTINTERNALNAMES,
5563                        message 
5564                        ("Internal identifier %q is not distinguishable from %q "
5565                         "in the first %d characters except by lookalike characters",
5566                         uentry_getName (e),
5567                         uentry_getName (oe),
5568                         numchars),
5569                        uentry_whereLast (e)))
5570                     {
5571                       uentry_showWhereAny (oe);
5572                       uentry_setHasNameError (oe);
5573                       return TRUE;
5574                     }
5575                 }
5576             }
5577         } end_usymtab_entries ;
5578       
5579       ttab = ttab->env;
5580     }
5581
5582   return FALSE;
5583 }
5584
5585 void usymtab_checkDistinctName (uentry e, int scope)
5586    /*@globals utab, globtab@*/
5587 {
5588   bool hasError = FALSE;
5589   fileloc where = uentry_whereLast (e);
5590
5591   if (!fileloc_isPreproc (where)  && !fileloc_isBuiltin (where))
5592     {
5593       if (scope == globScope)
5594         {
5595           if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
5596             {
5597               hasError = checkDistinctExternalName (e);
5598             }
5599         }
5600       
5601       if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
5602         {
5603           hasError = checkDistinctInternalName (e);
5604         }
5605     }
5606
5607   if (hasError)
5608     {
5609             uentry_setHasNameError (e);
5610     }
5611 }
5612
This page took 0.496136 seconds and 5 git commands to generate.