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