]> andersk Git - splint.git/blob - src/usymtab.c
bdb71f9e080f5933548ba434b3c82afc3491b17d
[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
2051       cstring name = cstring_fromChars(reader_getWord(&s) );
2052       cstring temp;
2053       ue = usymtab_lookup ( name );
2054
2055       cstring_free(name);
2056       
2057       preconditions = constraintList_undefined;
2058       postconditions = constraintList_undefined;
2059       
2060       if (!uentry_isValid(ue) )
2061         {
2062           llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2063         }
2064       s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2065
2066       temp = cstring_fromChars (reader_getWord(&s) );
2067       
2068       if (cstring_compareLit (temp,"pre:") == 0 )
2069         {
2070           preconditions = constraintList_undump (f);
2071         }
2072       else
2073         {
2074           if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2075             llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2076         }
2077       
2078       cstring_free(temp);
2079       
2080       s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2081
2082       temp = cstring_fromChars(reader_getWord(&s) );
2083       if (cstring_compareLit (temp, "post:") == 0 )
2084         {
2085           postconditions = constraintList_undump (f);
2086         }
2087       else
2088         {
2089           if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2090             llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2091         }
2092       
2093       cstring_free (temp);
2094
2095       uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2096       uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2097       
2098       s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2099     }
2100     
2101   dbgload = FALSE;
2102   sfree (os);
2103 }
2104
2105 /*
2106 ** file scope for static variables
2107 */
2108
2109 void
2110 usymtab_enterFile ()
2111   /*@globals utab, globtab, filetab@*/
2112   /*@modifies filetab@*/
2113 {
2114   llassert (utab == globtab);
2115
2116   # if 0
2117   /* check globals */
2118   
2119   usymtab_entries (globtab, ue)
2120     {
2121       if (sRef_hasDerived (uentry_getSref (ue)))
2122         {
2123           fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2124           fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2125         }
2126     } end_usymtab_entries ;
2127
2128   # endif
2129
2130   usymtab_enterScope ();
2131   filetab = utab;
2132 }
2133
2134 void
2135 usymtab_exitFile ()
2136    /*@globals utab, filetab@*/
2137    /*@modifies filetab, utab@*/
2138 {
2139   
2140   llassert (utab->lexlevel == 1);
2141
2142   usymtab_exitScope (exprNode_undefined);
2143   filetab = NULL;
2144 }
2145
2146 void
2147 usymtab_enterScope ()
2148   /*@globals utab, globtab, filetab@*/
2149   /*@modifies utab@*/
2150 {
2151   usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2152           
2153   /* unconditional scope: optimize to avoid copy */
2154   t->aliases = aliasTable_copy (utab->aliases); 
2155   utab = t;
2156   
2157   llassert (usymtab_isDefined (t->env));
2158   
2159   if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2160     {
2161       noshadowerror = TRUE;
2162       usymtab_handleParams ();
2163       noshadowerror = FALSE;
2164     }
2165 }
2166
2167 /*
2168 ** setup external references:
2169 **    o only, unique params alias external args
2170 **    o other params may alias anything of their type
2171 */
2172  
2173 static void
2174 usymtab_handleParams (void)
2175   /*@globals utab, globtab, filetab@*/
2176   /*@modifies utab, globtab@*/
2177 {
2178   usymtab ptab = utab->env;
2179   uentry fcn = context_getHeader ();
2180
2181   usymtab_entries (ptab, param)
2182     {
2183       uentry ue;
2184
2185       if (!uentry_isYield (param))
2186         {
2187           sRef uref;
2188           sRef pref = uentry_getSref (param);
2189
2190           /* Could be a global. */
2191           
2192           if (uentry_isAnyParam (param))
2193             {     
2194               ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2195                                         uentry_getType (param),
2196                                         fileloc_copy (uentry_whereDeclared (param)),
2197                                         FALSE);
2198               
2199               uentry_copyState (ue, param);
2200               uentry_setRefParam (ue);
2201               
2202               ue = usymtab_supEntrySrefReturn (ue);
2203               
2204               /* must be after supercede! */
2205               
2206               if (!sRef_stateKnown (pref))
2207                 {
2208                   uentry_setDefState (ue, SS_DEFINED);
2209                   uentry_setDefState (param, SS_DEFINED);
2210                 }
2211               else
2212                 {
2213                   if (sRef_isStateSpecial (pref))
2214                     {
2215                       uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2216                       /* evans 2002-01-01: should be unnecessary, the pre clauses
2217                       **    set the state if necessary.
2218                       */
2219                     }
2220                   else
2221                     {
2222                       uentry_setDefState (ue, sRef_getDefState (pref));
2223                     }
2224                 }
2225               
2226               uref = uentry_getSref (ue);
2227               
2228               if (sRef_isStack (uref))
2229                 {
2230                   alkind pkind = sRef_getAliasKind (pref);
2231                   
2232                   if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2233                       && !alkind_isStack (pkind))
2234                     {
2235                       sRef_setAliasKind (uref, pkind, fileloc_undefined);
2236                       sRef_setOrigAliasKind (uref, pkind);
2237                     }
2238                   else
2239                     {
2240                       sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2241                       sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2242                       
2243                       if (uentry_isOut (param))
2244                         {
2245                           ;
2246                         }
2247                       else
2248                         {
2249                           sRef_setDefined (uref, fileloc_undefined);
2250                         }
2251                     }
2252                   
2253                 }
2254               
2255               usymtab_addMustAlias (uref, pref);   
2256               
2257               if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2258                 {
2259                   /*
2260                   ** This is needed for detecting possibly aliased parameters.
2261                   */
2262
2263                   sRef s = sRef_makeExternal (uref);
2264                   usymtab_addMustAlias (uref, s);   
2265                 }
2266               
2267               if (sRef_isKillRef (pref))
2268                 {
2269                   sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2270                   sRef_setOrigAliasKind (uref, AK_KILLREF);
2271                 }
2272               else if (sRef_isRefCounted (uref))
2273                 {
2274                   sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2275                 }
2276               else
2277                 {
2278                   /* was AK_UNIQUE */
2279                   sRef_setOrigAliasKind (uref, AK_LOCAL);
2280                 }
2281             }
2282           else
2283             {
2284             }
2285         }
2286     } end_usymtab_entries;
2287   
2288   
2289   if (uentry_hasStateClauseList (fcn))
2290     {
2291       stateClauseList clauses = uentry_getStateClauseList (fcn);
2292       
2293       stateClauseList_preElements (clauses, cl)
2294         {
2295           fileloc loc = stateClause_loc (cl);
2296           sRefSet osrs = sRefSet_undefined;
2297           sRefSet srs;
2298           
2299           if (stateClause_isGlobal (cl))
2300             {
2301               DPRINTF (("Global Marker: %s",
2302                         sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2303               llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2304               srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2305               osrs = srs;
2306             }
2307           else
2308             {
2309               srs = stateClause_getRefs (cl);
2310             }
2311           
2312           sRefSet_elements (srs, el)
2313             {
2314               sRef base = sRef_getRootBase (el);
2315               sRef sb = sRef_updateSref (el);
2316
2317               if (sRef_isResult (base))
2318                 {
2319                   ; /* nothing to do before */
2320                 }
2321               else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2322                 {
2323                   if (stateClause_setsMetaState (cl))
2324                     {
2325                       /* copied from exprNode.c:3040 */
2326                       qual ql = stateClause_getMetaQual (cl);
2327                       annotationInfo ainfo = qual_getAnnotationInfo (ql);
2328                       metaStateInfo minfo = annotationInfo_getState (ainfo);
2329                       cstring key = metaStateInfo_getName (minfo);
2330                       int mvalue = annotationInfo_getValue (ainfo);
2331                       
2332                       DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2333                           
2334                       if (sRef_isResult (base))
2335                         {
2336                           BADBRANCH;
2337                         }
2338                       else 
2339                         {
2340                           sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2341                         }
2342                     }
2343                   else
2344                     {
2345                       sRefMod modf = stateClause_getEntryFunction (cl);
2346                       
2347                       if (modf != NULL)
2348                         {
2349                           sRefSet aliases = usymtab_allAliases (sb);
2350                           
2351                           modf (sb, loc);
2352                           
2353                           sRefSet_elements (aliases, sr)
2354                             {
2355                               modf (sr, loc);
2356                             } end_sRefSet_elements ;
2357                             
2358                           sRefSet_free (aliases);
2359                         }
2360                     }
2361                 }
2362               else
2363                 {
2364                   if (sRef_isValid (base))
2365                     {
2366                       DPRINTF (("Base: %s", sRef_unparseFull (base)));
2367                       BADBRANCH;
2368                     }
2369                 }
2370             } end_sRefSet_elements ;      
2371         } end_stateClauseList_preElements ;
2372     }
2373 }
2374
2375 void
2376 usymtab_enterFunctionScope (uentry fcn)
2377   /*@globals utab, filetab, globtab@*/
2378   /*@modifies utab@*/
2379 {
2380   usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2381
2382   DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2383
2384   if (utab->lexlevel != fileScope)
2385     {
2386       if (utab->lexlevel > fileScope)
2387         {
2388           llparseerror (cstring_makeLiteral ("New function scope inside function"));
2389           
2390           while (utab->lexlevel > fileScope)
2391             {
2392               /*@i@*/ utab = usymtab_dropEnv (utab);
2393               /*@-branchstate@*/
2394             }
2395           /*@=branchstate@*/
2396         }
2397       else
2398         {
2399           llfatalbug (cstring_makeLiteral ("New function not inside file."));
2400         }
2401     /*@-branchstate@*/ } /*@=branchstate@*/
2402
2403   utab = t;
2404   
2405   DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2406
2407   globSet_allElements (uentry_getGlobs (fcn), el)
2408     {
2409       DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2410       
2411       if (sRef_isUndefGlob (el))
2412         {
2413           usymId index = sRef_getScopeIndex (el);
2414           sRef sr = sRef_updateSref (el);
2415           fileloc loc = uentry_whereEarliest (fcn);
2416         
2417           DPRINTF (("update: %s", sRef_unparseFull (sr)));
2418           DPRINTF (("Undef!"));
2419           if (sRef_isFileStatic (el))
2420             {
2421               ctype ct = sRef_getType (el);
2422               uentry ue;
2423               
2424               llassert (usymtab_isDefined (filetab));
2425
2426               ue = usymtab_fetchIndex (filetab, index);
2427               
2428               if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2429                 {
2430                   sRef_setAllocated (sr, loc);
2431                 }
2432               else
2433                 {
2434                   sRef_setUndefined (sr, loc);
2435                 }
2436             }
2437           else
2438             {
2439               uentry ue = globtab->entries[index];
2440               ctype ct = uentry_getType (ue);
2441               
2442               if (ctype_isArray (ct) || ctype_isSU (ct))
2443                 {
2444                   sRef_setAllocated (sr, loc);
2445                 }
2446               else
2447                 {
2448                   sRef_setUndefined (sr, loc);
2449                 }
2450             }
2451         }
2452       else if (sRef_isAllocated (el))
2453         {
2454           sRef sr = sRef_updateSref (el);
2455           fileloc loc = uentry_whereEarliest (fcn);
2456           
2457           sRef_setAllocated (sr, loc);
2458         }
2459       else if (sRef_isPartial (el))
2460         {
2461           sRef sr = sRef_updateSref (el);
2462           fileloc loc = uentry_whereEarliest (fcn);
2463
2464           sRef_setPartial (sr, loc);
2465         }
2466       else
2467         {
2468           /*
2469           sRef sr = sRef_updateSref (el);
2470           fileloc loc = uentry_whereEarliest (fcn);
2471
2472           sRef_setDefined (sr, loc);
2473           */
2474
2475           /* defined */
2476           /* shouldn't need to do anything! */ 
2477         }
2478     } end_globSet_allElements;
2479
2480   DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2481 # ifdef DEBUGSPLINT
2482   usymtab_checkAllValid ();
2483 # endif
2484 }
2485
2486 static void
2487 usymtab_caseBranch (void)
2488   /*@modifies utab@*/
2489 {
2490   usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2491   utab = t;
2492 }
2493
2494 void
2495 usymtab_switchBranch (/*@unused@*/ exprNode s)
2496   /*@modifies utab@*/
2497 {
2498   usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2499
2500   t->aliases = aliasTable_copy (utab->aliases);
2501   utab = t;
2502 }
2503
2504 void
2505 usymtab_trueBranch (/*@only@*/ guardSet guards)
2506   /*@modifies utab@*/
2507 {
2508   usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2509
2510   /*
2511   ** not true! (could be in a macro)
2512   **
2513   ** llassertprint (utab->lexlevel > paramsScope,
2514   ** ("not in scope: %s", usymtab_unparseLocal ()));
2515   **
2516   */
2517
2518   guardSet_free (t->guards);
2519   t->guards = guards;
2520   
2521   aliasTable_free (t->aliases);
2522   t->aliases = aliasTable_copy (utab->aliases);
2523   
2524   utab = t;
2525 }
2526
2527 /*
2528 ** consider,
2529 ** 
2530 **   { int a; if (...) a = 3; < a may be undefined here!
2531 **
2532 */
2533
2534 void
2535 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2536 {
2537   /*
2538   ** add a false branch
2539   ** (could be done more efficiently as a special case, but
2540   ** it is better to only maintain one version of the code)
2541   */
2542
2543   if (utab->kind != US_TBRANCH 
2544       && context_inIterDef ())
2545     {
2546       usymtab_exitScope (expr);
2547     }
2548   else
2549     {
2550       DPRINTF (("pop true branch.."));
2551       usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2552       usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2553     }
2554 }
2555
2556 void
2557 usymtab_popCaseBranch () /*@modifies utab@*/
2558 {
2559   llassert (utab->kind == US_CBRANCH);
2560   usymtab_quietPlainExitScope ();
2561 }
2562
2563 void
2564 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2565 {
2566   /*
2567   ** add a false branch that must return --- that is,
2568   ** the true branch is always executed!
2569   */
2570   
2571   usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2572   usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2573 }
2574
2575 void
2576 usymtab_popOrBranch (exprNode pred, exprNode expr)
2577   /*@modifies utab@*/
2578 {
2579   bool mustReturn;
2580   usymtab env = utab->env;
2581   usymtab otab = utab;
2582   int i = 0;
2583
2584   llassert (env != NULL);
2585
2586   if (exprNode_isError (expr))
2587     {
2588       mustReturn = FALSE;
2589     }
2590   else
2591     {
2592       mustReturn = exprNode_mustEscape (expr);
2593     }
2594
2595   
2596   llassert (utab->kind == US_TBRANCH);
2597
2598   /*
2599   ** merge each entry in table with its original
2600   ** unless execution cannot continue after this branch
2601   */
2602
2603   for (i = 0; i < utab->nentries; i++)
2604     {
2605       uentry current = utab->entries[i];
2606       uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2607
2608       uentry_mergeState (old, current, exprNode_loc (expr), 
2609                          mustReturn, FALSE, TRUE, ORCLAUSE);
2610     }
2611   
2612   
2613   if (mustReturn)
2614     {
2615       env->guards = guardSet_levelUnionFree (env->guards, 
2616                                              guardSet_invert (exprNode_getGuards (pred)), 
2617                                              env->lexlevel);
2618     }
2619   else
2620     {
2621       env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2622     }
2623  
2624   /* env is now utab */
2625   usymtab_quietPlainExitScope ();
2626 }
2627
2628 /*
2629 ** case syntax in C is very unrestricted.  This is unfortunate.
2630 **
2631 ** A switch case is ended either by a new case or default, or
2632 ** a close } that may close the switch or some other control
2633 ** structure.  
2634 */
2635
2636 bool
2637 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2638   /*@modifies utab@*/
2639 {
2640   bool mustBreak = usymtab_mustBreak (utab);
2641   bool mustReturn = usymtab_mustEscape (utab);
2642   usymtab stab = utab;
2643
2644   DPRINTF (("New case!"));
2645
2646   /*
2647   ** Find last case (or outer switch)
2648   */
2649
2650   while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2651     {
2652       stab = stab->env;
2653       llassert (stab != GLOBAL_ENV);
2654     }
2655   
2656   while (stab->kind == US_CBRANCH)
2657     {
2658       stab = stab->env;
2659       llassert (stab != GLOBAL_ENV);
2660     }
2661   
2662   /*
2663   ** if its a fall through case, merge in outside entries and last case.
2664   **
2665   ** e.g.,
2666   **        ...
2667   **        switch
2668   **          case 1: x = 3; <fall through>
2669   **          case 2: << x may not be defined
2670   **
2671   */
2672
2673   if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2674     {
2675       llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2676
2677       usymtab_entries (utab, ue)  /* but, keep track of used variables */
2678         {
2679           uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2680
2681           llassert (uentry_isValid (old));
2682
2683           /* modifies ue, not old */
2684           
2685           uentry_mergeState (ue, old, exprNode_loc (last),
2686                              FALSE, FALSE, TRUE, CASECLAUSE); 
2687         } end_usymtab_entries;
2688
2689       utab->aliases = aliasTable_levelUnion (utab->aliases, 
2690                                              stab->aliases, utab->lexlevel);
2691       
2692       /* 
2693       ** No need for a new branch.
2694       */
2695       
2696       return FALSE;
2697     }
2698   else
2699     {
2700       usymtab_caseBranch ();
2701       /*@-mustfree@*/ /*< utab->aliases >*/
2702       utab->aliases = aliasTable_copy (stab->aliases);
2703       /*@=mustfree@*/
2704       
2705       return TRUE;
2706     }
2707 }
2708
2709 /*
2710 ** for && (both pred and expr are executed)
2711 */
2712
2713 void
2714 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2715   /*@modifies utab@*/
2716 {
2717   usymtab env = utab->env;
2718   usymtab otab= utab;
2719   int i = 0;
2720
2721   llassert (utab->kind == US_TBRANCH);
2722
2723   /*
2724   ** merge each entry in table with its original
2725   ** unless execution cannot continue after this branch
2726   */
2727
2728   for (i = 0; i < utab->nentries; i++)
2729     {
2730       uentry current = utab->entries[i];
2731       sRef   tref = uentry_getSref (current);
2732       uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2733       sRef   oref = uentry_getSref (old);
2734
2735       /* note that is current is in a nested branch,
2736          it may create a "new" old entry. */
2737
2738       llassert (uentry_isValid (old));
2739       uentry_mergeState (old, current, exprNode_loc (expr), 
2740                          FALSE, FALSE, TRUE, ANDCLAUSE);
2741
2742       /*
2743       ** if is it defined by the second clause, then it should be defined.
2744       */
2745
2746       if (sRef_isAnyDefined (tref)
2747           && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2748         {
2749           sRef_setDefined (oref, g_currentloc);
2750         }
2751     }
2752
2753   utab->guards = guardSet_levelUnionFree (utab->guards, 
2754                                           guardSet_invert (exprNode_getGuards (pred)), 
2755                                           utab->lexlevel);
2756   utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2757
2758   usymtab_quietPlainExitScope ();
2759
2760   }
2761
2762 /*
2763 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2764 ** Only branches which do not return (except possibly the last branch) are included.
2765 **
2766 ** Conditionally merge state from all CBRANCHes.
2767 **
2768 ** If allpaths is TRUE, then all possible executions go through some switch 
2769 ** case, and the original scope is not merged.
2770 */
2771
2772 void
2773 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2774   /*@modifies utab@*/
2775 {
2776   usymtab ttab = utab;
2777   usymtab stab = ttab;
2778   usymtab ltab = ttab;
2779   bool lastMustReturn = usymtab_mustEscape (utab);
2780   int i;
2781   
2782     
2783   while (stab->kind == US_CBRANCH)
2784     {
2785       stab = stab->env;
2786       llassert (stab != GLOBAL_ENV);
2787     }
2788
2789   while (stab->kind == US_NORMAL)
2790     {
2791       stab = stab->env;
2792       llassert (stab != GLOBAL_ENV);
2793     }
2794
2795   llassert (stab->kind == US_SWITCH);
2796
2797   /* go to the scope outside the switch (US_SWITCH is just a marker! */
2798   stab = stab->env; 
2799   llassert (stab != GLOBAL_ENV);
2800
2801   
2802   ttab = ttab->env;
2803   llassert (usymtab_isDefined (ttab));
2804   
2805   if (ttab->kind == US_CBRANCH)
2806     {
2807       /* was quietPlainExitScope --- but, can't free it yet! */
2808       utab = utab->env;
2809       llassert (utab != GLOBAL_ENV);
2810
2811       while (ttab->kind == US_CBRANCH)
2812         {
2813           /*
2814           ** (from popTrueBranch)
2815           */      
2816           
2817           bool mustReturn = usymtab_mustEscape (ttab);
2818           bool mustBreak = usymtab_mustBreak (ttab);
2819           
2820           usymtab_entries (ttab, current)
2821             {
2822               uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2823                            /*@=compmempass@*/ 
2824               
2825               /*
2826               ** note that is this is in a nested branch,
2827               ** it may create a "new" old entry. 
2828               */
2829            
2830               if (uentry_isValid (old))
2831                 {
2832                   if (lastMustReturn)
2833                     {
2834                       uentry_mergeUses (current, old);
2835                       uentry_setState (old, current);
2836                     }
2837                   else
2838                     {
2839                       uentry_mergeState (old, current, exprNode_loc (sw),
2840                                          mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2841                     }
2842                 }
2843               else
2844                 {
2845                   ;
2846                 }
2847             } end_usymtab_entries;
2848           
2849           /*
2850           ** if entry is not in symbol table for this case, merge with pre-switch
2851           ** table
2852           */
2853           
2854           if (!mustReturn && !mustBreak)
2855             {
2856               usymtab_entries (stab, current)
2857                 {
2858                   if (!usymtab_indexFound (usymtab_getIndex (ttab, uentry_rawName (current))))
2859                     {
2860                       uentry old = /*@-compmempass@*/
2861                         usymtab_lookupAux (ltab, uentry_rawName (current));
2862                       /*@=compmempass@*/
2863
2864                       llassert (uentry_isValid (old));
2865                       uentry_mergeState (old, current, exprNode_loc (sw),
2866                                          FALSE, FALSE, TRUE, SWITCHCLAUSE);
2867                     }
2868                 } end_usymtab_entries;
2869             }
2870           
2871           ltab->env = ttab->env; 
2872           ttab = ltab->env;
2873
2874           /*
2875           ** Suprious error, becuase of environments.
2876           */
2877
2878           /*@i1@*/ utab = ltab;
2879
2880           lastMustReturn = FALSE;
2881           /*@-branchstate@*/ 
2882         }
2883     }
2884   /*@=branchstate@*/
2885
2886   /*
2887   ** now, there is one US_CBRANCH.  Merge this with the stab.
2888   */
2889   
2890     
2891   for (i = 0; i < ltab->nentries; i++)
2892     {
2893       uentry current = ltab->entries[i];
2894       uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2895       
2896       /* note that is this is in a nested branch,
2897          it may create a "new" old entry. */
2898       
2899          
2900       if (uentry_isValid (old))
2901         {
2902           if (allpaths)
2903             {
2904               uentry_mergeUses (current, old);
2905               uentry_setState (old, current);
2906             }
2907           else
2908             {
2909               uentry_mergeState (old, current, exprNode_loc (sw), 
2910                                  FALSE, FALSE, TRUE, SWITCHCLAUSE);
2911             }
2912         }
2913       else
2914         {
2915                 }
2916     }
2917   
2918   /*
2919   ** exit the switch
2920   */
2921   
2922   
2923   /*
2924   ** switch may or may not be followed by a new scope
2925   */
2926
2927   if (utab->kind == US_SWITCH)
2928     {
2929       usymtab_quietPlainExitScope ();  
2930     }
2931   else
2932     {
2933       usymtab_quietPlainExitScope ();
2934       llassert (utab->kind == US_SWITCH);
2935       usymtab_quietPlainExitScope ();   
2936     }
2937
2938   }
2939
2940 static void 
2941 updateNullState (sRef el, /*@notnull@*/ usymtab ttab, 
2942                  /*@notnull@*/ usymtab ftab, bool trueGuard)
2943 {
2944   sRef base = sRef_getRootBase (el);
2945   int level = sRef_lexLevel (base);        
2946     
2947   if (sRef_isCvar (base))
2948     {
2949       usymId index = sRef_getScopeIndex (base);
2950       uentry ue = usymtab_getRefTab (ttab, level, index);
2951
2952       if (!uentry_isLset (ue)) 
2953         {
2954           sRef sr = uentry_getSref (ue);
2955
2956           if (trueGuard)
2957             {
2958               sRef_setDerivNullState (sr, el, NS_NOTNULL);
2959             }
2960           else 
2961             {
2962               if (!guardSet_isGuarded (ttab->guards, el) 
2963                   && !sRef_isNotNull (sr))
2964                 {
2965                   DPRINTF (("Here! %s / %s",
2966                             sRef_unparseFull (sr),
2967                             sRef_unparseFull (el)));
2968                   sRef_setDerivNullState (sr, el, NS_DEFNULL);
2969                 }
2970             }
2971         }
2972       else
2973         {
2974           ;
2975         }
2976       
2977       ue = usymtab_getRefTab (ftab, level, index);
2978       
2979       if (!uentry_isLset (ue)) 
2980         {
2981           sRef sr = uentry_getSref (ue);
2982           
2983           if (!trueGuard) /* yikes!  forgot the ! */
2984             {
2985               sRef_setDerivNullState (sr, el, NS_NOTNULL);
2986             }
2987           else 
2988             {
2989               
2990               if (!guardSet_isGuarded (ftab->guards, el)
2991                   && !sRef_isNotNull (sr))
2992                 {
2993                   sRef_setDerivNullState (sr, el, NS_DEFNULL);
2994                 }
2995             }
2996         }
2997       else
2998         {
2999           ;
3000         }
3001     }  
3002 }
3003
3004 void
3005 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch, 
3006                      bool isOpt, clause cl)
3007      /*@modifies utab@*/
3008 {
3009   int i = 0;
3010   usymtab ftab = utab;
3011   usymtab ttab = utab->env;
3012
3013   fileloc loc;
3014   usymtab env;
3015   guardSet guards = exprNode_getGuards (pred);
3016   sRefSet tguards = guardSet_getTrueGuards (guards);
3017   sRefSet fguards = guardSet_getFalseGuards (guards);
3018   bool mustReturnT = exprNode_mustEscape (tbranch);
3019   bool mustReturnF = exprNode_mustEscape (fbranch);
3020
3021   DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
3022             bool_unparse (mustReturnT),
3023             bool_unparse (mustReturnF)));
3024
3025   if (exprNode_isDefined (fbranch))
3026     {
3027       loc = exprNode_loc (fbranch);
3028     }
3029   else
3030     {
3031       loc = exprNode_loc (tbranch);
3032     }
3033
3034   llassert (usymtab_isDefined (ttab));
3035   
3036   env = ttab->env;
3037   
3038   llassert (usymtab_isDefined (env));
3039   llassert (ftab->kind == US_FBRANCH);
3040   llassert (ttab->kind == US_TBRANCH);
3041
3042   /*
3043   ** For each element that is true guarded (i.e., if (x != NULL)) 
3044   **          make x = null in false branch,
3045   **          and x = notnull in true branch.
3046   **          unless x was set locally in that branch.
3047   ** For each element that is false guarded (x == NULL) 
3048   **          make x = null in true, notnull in false.
3049   **                      
3050   ** For each element that is either guarded (pred(x)) 
3051   **     
3052   */
3053   
3054   sRefSet_allElements (tguards, el)
3055     {
3056       updateNullState (el, ttab, ftab, TRUE);
3057     } end_sRefSet_allElements;
3058     
3059   sRefSet_allElements (fguards, el)
3060     {
3061       updateNullState (el, ttab, ftab, FALSE);
3062     } end_sRefSet_allElements;
3063
3064   /*
3065   ** 
3066   ** if an entry is in both true and false, merge the entries,
3067   ** then replace original with new state.
3068   **
3069   ** if an entry is in one table, merge it with the original.
3070   */
3071   
3072   DPRINTF (("ftab: %d", ftab->nentries));
3073
3074   for (i = 0; i < ftab->nentries; i++)
3075     {
3076       uentry fthis = ftab->entries[i];
3077       uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3078       usymId tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3079       
3080       DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3081           
3082       if (uentry_isUndefined (old))
3083         {
3084           /* possible entry was added as an undefined id */
3085           DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3086           continue;
3087         }
3088       
3089       if (usymtab_indexFound (tindex))
3090         {
3091           uentry tthis = ttab->entries[tindex];
3092
3093           /* note that is this is in a nested branch,
3094              it may create a "new" old entry. */
3095           
3096           if (!mustReturnF)
3097             {
3098               if (!mustReturnT)
3099                 {
3100                   uentry_mergeState (fthis, tthis, loc,
3101                                      mustReturnT, FALSE, FALSE, cl);
3102                 }
3103               else
3104                 {
3105                   uentry_mergeUses (fthis, tthis);
3106                 }
3107               
3108               uentry_setState (old, fthis);
3109               
3110               /*@-mustfree@*/ 
3111             } 
3112           /*@=mustfree@*/
3113           else
3114             {
3115               uentry_setState (old, tthis);
3116               uentry_mergeState (old, fthis, loc, mustReturnF, 
3117                                  TRUE, FALSE, cl);
3118             }
3119           
3120           ttab->entries[tindex] = uentry_undefined;
3121           uentry_free (tthis);
3122         }
3123       else
3124         {
3125           uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3126         }
3127     }
3128
3129   for (i = 0; i < ttab->nentries; i++)
3130     {
3131       uentry current = ttab->entries[i];
3132       
3133       DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3134       
3135       if (!uentry_isUndefined (current)) 
3136         {
3137           uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3138
3139           DPRINTF (("Old: %s", uentry_unparseFull (old)));
3140
3141           if (uentry_isUndefined (old))
3142             {
3143               llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3144               continue;
3145             }
3146
3147           if (mustReturnF)
3148             {
3149               uentry_mergeUses (current, old); 
3150               uentry_setState (old, current);
3151             }
3152           else
3153             {
3154               /*
3155               ** Assumes false branch is a fall-through if
3156               ** fbranch is not defined.  This is true, unless
3157               ** where was some greivous error in processing
3158               ** the else branch of an if-then, in which case
3159               ** this is probably the right thing to do anyway.
3160               */
3161
3162               uentry_mergeState (old, current, loc, mustReturnT, 
3163                                  FALSE, isOpt, cl);
3164             }
3165
3166           DPRINTF (("==> %s", uentry_unparseFull (old)));
3167         }
3168     }
3169   
3170   /*
3171   ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3172   ** if they are present.
3173   */
3174
3175   llassert (NOALIAS (env->aliases, ttab->aliases));
3176   llassert (NOALIAS (env->aliases, ftab->aliases));
3177
3178   aliasTable_free (env->aliases);  
3179
3180   env->aliases = aliasTable_levelUnionNew (ttab->aliases, 
3181                                            ftab->aliases, env->lexlevel);
3182
3183   aliasTable_fixSrefs (env->aliases);
3184
3185   DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3186   
3187   /* exit true and false scopes */
3188   usymtab_quietPlainExitScope ();
3189   usymtab_quietPlainExitScope ();
3190   
3191   if (mustReturnT)
3192     {
3193       utab->guards = guardSet_levelUnionFree 
3194         (utab->guards, 
3195          guardSet_invert (exprNode_getGuards (pred)), 
3196          utab->lexlevel);
3197     }
3198
3199   if (mustReturnF)
3200     {
3201       utab->guards = guardSet_levelUnion (utab->guards, 
3202                                           exprNode_getGuards (pred), 
3203                                           utab->lexlevel);
3204     }
3205
3206   DPRINTF (("Here."));
3207 }
3208
3209 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3210   while (utab->kind == US_CBRANCH)
3211     {
3212       usymtab_quietPlainExitScope ();
3213     }
3214
3215   llassert (utab->kind != US_CBRANCH);
3216 }
3217
3218 void
3219 usymtab_altBranch (/*@only@*/ guardSet guards)
3220   /*@modifies utab@*/
3221 {
3222   usymtab t;
3223   usymtab parent = utab->env;
3224
3225   t = usymtab_create (US_FBRANCH, utab, FALSE);
3226
3227   /*
3228   ** If we are in a case, need to close it.  The C syntax
3229   ** is very liberal, so this kludge is necessary.
3230   */
3231
3232   usymtab_fixCases ();
3233
3234   DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3235
3236   llassert (utab->kind == US_TBRANCH);
3237   llassert (parent != GLOBAL_ENV);
3238   
3239   guardSet_free (t->guards);
3240   t->guards = guards;
3241   
3242   aliasTable_free (t->aliases);
3243   t->aliases = aliasTable_copy (parent->aliases);
3244   
3245   utab = t;
3246 }
3247
3248 void
3249 usymtab_allDefined (void)
3250    /*@globals utab, globtab@*/
3251 {
3252   int i;
3253
3254   llassert (utab == globtab);
3255
3256   for (i = 0; i < utab->nentries; i++)
3257     {
3258       uentry e = utab->entries[i];
3259
3260       if (uentry_isPriv (e))
3261         {
3262          ; /* no need to define it */
3263         }
3264       else
3265         {
3266           if (context_getFlag (FLG_SPECUNDECL))
3267             {
3268               fileloc sloc = uentry_whereSpecified (e);
3269               fileloc dloc = uentry_whereDeclared (e);
3270
3271               if (fileloc_isDefined (sloc) 
3272                   && !uentry_isFakeTag (e)
3273                   && !fileloc_isDefined (dloc))
3274                 {
3275                   voptgenerror 
3276                     (FLG_SPECUNDECL,
3277                      message ("%s %q specified but not declared",
3278                               ekind_capName (uentry_getKind (e)),
3279                               uentry_getName (e)),
3280                      sloc);
3281                 }
3282             }
3283           
3284           if (!uentry_isCodeDefined (e))
3285             {
3286               fileloc dloc = uentry_whereDeclared (e);
3287               
3288               if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3289                 {
3290                  ;
3291                 }
3292               else if (fileloc_isDefined (dloc))
3293                 {
3294                   if (!uentry_isAnyTag (e))
3295                     {
3296                       if (fileloc_isUser (dloc))
3297                         {
3298                           voptgenerror 
3299                             (FLG_DECLUNDEF,
3300                              message ("%s %q declared but not defined",
3301                                       ekind_capName (uentry_getKind (e)),
3302                                       uentry_getName (e)),
3303                              dloc);
3304                           DPRINTF (("decl: %s", uentry_unparseFull (e)));
3305                         }
3306                     }
3307                 }
3308               else
3309                 {
3310                   fileloc sloc = uentry_whereSpecified (e);
3311
3312                   if (fileloc_isDefined (sloc) 
3313                       && !fileloc_isImport (sloc)
3314                       && !fileloc_isLib (sloc)
3315                       && !fileloc_isPreproc (sloc)
3316                       && !uentry_isFakeTag (e))
3317                     {
3318                       if (uentry_isVariable (e) || uentry_isFunction (e))
3319                         {
3320                           voptgenerror 
3321                             (FLG_SPECUNDEF,
3322                              message ("%s %q specified but not declared or defined",
3323                                       ekind_capName (uentry_getKind (e)),
3324                                       uentry_getName (e)),
3325                              sloc);
3326                         }
3327                       else
3328                         {
3329                           voptgenerror 
3330                             (FLG_SPECUNDEF,
3331                              message ("%s %q specified but not defined",
3332                                       ekind_capName (uentry_getKind (e)),
3333                                       uentry_getName (e)),
3334                              sloc);
3335                         }
3336                     }
3337                 }
3338             }
3339         }
3340     }
3341 }
3342
3343 void usymtab_exportHeader (void)
3344      /*@globals utab@*/
3345 {
3346   int i;
3347
3348   for (i = 0; i < utab->nentries; i++)
3349     {
3350       uentry ce = utab->entries[i];
3351
3352       if (!uentry_isDatatype (ce) 
3353           && !uentry_isAnyTag (ce) 
3354           && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3355           && !uentry_isExternal (ce)
3356           && !uentry_isForward (ce))
3357         {
3358           fileloc fwhere = uentry_whereDeclared (ce);
3359
3360           if (fileloc_isUndefined (fwhere)
3361               && uentry_isFunction (ce))
3362             {
3363               fwhere = uentry_whereDefined (ce);
3364             }
3365
3366           if (fileloc_isDefined (fwhere) 
3367               && !fileloc_isHeader (fwhere)
3368               && !fileloc_isXHFile (fwhere)
3369               && !(fileloc_isSpecialFile (fwhere)
3370                    && !context_getFlag (FLG_UNUSEDSPECIAL)))
3371             {
3372               if (uentry_isVariable (ce))
3373                 {
3374                   if (optgenerror
3375                       (FLG_EXPORTHEADERVAR,
3376                        message ("%s %q exported but not declared in header file", 
3377                                 ekind_capName (uentry_getKind (ce)),
3378                                 uentry_getName (ce)),
3379                        fwhere))
3380                     {
3381                       uentry_showDefSpecInfo (ce, fwhere);
3382                     }
3383                 }
3384               else
3385                 {
3386                   if (!uentry_isIter (ce)
3387                       && !uentry_isEndIter (ce)
3388                       && !uentry_isExpandedMacro (ce))
3389                     {
3390                       if (uentry_isFunction (ce) 
3391                           && cstring_equalLit (uentry_rawName (ce), "main"))
3392                         {
3393                           ; /* no error for main */
3394                         }
3395                       else
3396                         {
3397                           if (optgenerror
3398                               (FLG_EXPORTHEADER,
3399                                message ("%s %q exported but not declared "
3400                                         "in header file", 
3401                                         ekind_capName (uentry_getKind (ce)),
3402                                         uentry_getName (ce)),
3403                                fwhere))
3404                             {
3405                               uentry_showDefSpecInfo (ce, fwhere);
3406                             }
3407                         }
3408                     }
3409                 }
3410             }
3411         }
3412     }
3413 }
3414
3415 void usymtab_exportLocal (void)
3416    /*@globals utab@*/
3417 {
3418   int i;
3419   
3420   for (i = 0; i < utab->nentries; i++)
3421     {
3422       uentry ce = utab->entries[i];
3423       
3424       if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce) 
3425           && !uentry_isEitherConstant (ce) 
3426           && !uentry_isIter (ce)
3427           && !uentry_isEndIter (ce)
3428           && !uentry_isExpandedMacro (ce)
3429           && uentry_isUsed (ce))
3430         {
3431           /* check static uses */
3432           filelocList fuses = uentry_getUses (ce);
3433           fileloc mod = uentry_whereDefined (ce);
3434           bool ok = filelocList_isEmpty (fuses);
3435           fileloc fwhere = uentry_whereDeclared (ce);
3436
3437           if (fileloc_isSpecialFile (fwhere)
3438               && !context_getFlag (FLG_UNUSEDSPECIAL))
3439             {
3440               ok = TRUE; /* no errors for special files */
3441             }
3442           else
3443             {
3444               filelocList_elements (fuses, uloc)
3445                 {
3446                   if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3447                     {
3448                       ok = TRUE;
3449                       /*@innerbreak@*/ break;
3450                     }
3451                 } end_filelocList_elements;
3452             }
3453
3454           if (!ok)
3455             {
3456               if (optgenerror
3457                   (FLG_EXPORTLOCAL,
3458                    message ("%s exported but not used outside %s: %q", 
3459                             ekind_capName (uentry_getKind (ce)),
3460                             fileloc_getBase (mod),
3461                             uentry_getName (ce)),
3462                    fwhere))
3463                 {
3464                   uentry_showDefSpecInfo (ce, fwhere);
3465                 }
3466             }
3467         }
3468     }
3469 }
3470
3471 void
3472 usymtab_allUsed (void)
3473   /*@globals utab@*/
3474 {
3475   int i;
3476   bool isFileStatic = usymtab_inFileScope ();
3477   cstring last_file = cstring_undefined;
3478
3479   for (i = 0; i < utab->nentries; i++)
3480     {
3481       bool hasError = FALSE;
3482       uentry ce = utab->entries[i];
3483       fileloc fwhere = uentry_whereDeclared (ce);
3484
3485       if (fileloc_isUndefined (fwhere))
3486         {
3487           fwhere = uentry_whereDefined (ce);
3488         }
3489
3490       if (fileloc_isInvalid (fwhere) 
3491           || fileloc_isLib (fwhere) 
3492           || fileloc_isBuiltin (fwhere)
3493           || ((fileloc_isSpecialFile (fwhere)
3494                || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3495               && !context_getFlag (FLG_UNUSEDSPECIAL)))
3496         {
3497           ;
3498         }
3499       else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3500         {
3501           cstring fname = fileloc_filename (fwhere);
3502
3503           if (cstring_isUndefined (last_file))
3504             {
3505               last_file = fname;
3506             }
3507           else if (cstring_equal (fname, last_file))
3508             {
3509             }
3510           else
3511             {
3512               cleanupMessages ();
3513               last_file = fname;
3514             } 
3515           
3516           if (uentry_isParam (ce))
3517             {
3518               if (context_inMacro ())
3519                 {
3520                   sRef cref = uentry_getSref (ce);
3521
3522                   if (uentry_isYield (ce))
3523                     {
3524                       ; /* no checks (for now) */
3525                     }
3526                   else if (sRef_isSafe (cref))
3527                     {
3528                       ; /* no error */
3529                     }
3530                   else
3531                     {
3532                       if (uentry_hasRealName (ce))
3533                         {
3534                           hasError = 
3535                             optgenerror (FLG_MACROPARAMS,
3536                                          message ("Macro parameter %q not used", 
3537                                                   uentry_getName (ce)),
3538                                          fwhere);
3539                         }
3540                     }
3541                 }
3542               else 
3543                 {
3544                   if (cstring_equalFree (uentry_getName (ce), 
3545                                          cstring_makeLiteral ("...")))
3546                     {
3547                       ;
3548                     }
3549                   else
3550                     {
3551                       hasError = optgenerror (FLG_PARAMUNUSED,
3552                                               message ("Parameter %q not used",
3553                                                        uentry_getName (ce)),
3554                                               fwhere);
3555                     }
3556                 }
3557             } /* isParam */
3558           else if (uentry_isFunction (ce) || uentry_isIter (ce))
3559             {
3560               if (fileloc_isUser (fwhere))
3561                 {
3562                   hasError = optgenerror
3563                     (FLG_FUNCUNUSED, 
3564                      message ("%q %q declared but not used", 
3565                               cstring_makeLiteral 
3566                               (uentry_isIter (ce) ? "Iterator" 
3567                                : (isFileStatic ? "File static function" : "Function")),
3568                               uentry_getName (ce)),
3569                      fwhere);
3570                 }
3571             }
3572           else if (uentry_isEndIter (ce))
3573             {
3574               ; /* no error (already reported for iter */
3575             }
3576           else if (uentry_isEnumConstant (ce))
3577             {
3578               if (fileloc_isUser (fwhere))
3579                 {
3580                   hasError = optgenerror
3581                     (FLG_ENUMMEMUNUSED,
3582                      message ("Enum member %q not used", 
3583                               uentry_getName (ce)),
3584                      fwhere);
3585                 }
3586             }
3587           else if (uentry_isConstant (ce))
3588             {
3589               if (fileloc_isUser (fwhere))
3590                 {
3591                   hasError = optgenerror
3592                     (FLG_CONSTUNUSED,
3593                      message ("Constant %q declared but not used", 
3594                               uentry_getName (ce)),
3595                      fwhere);
3596                 }
3597             }
3598           else if (uentry_isDatatype (ce))
3599             {
3600               if (fileloc_isUser (fwhere))
3601                 {
3602                   hasError = optgenerror
3603                     (FLG_TYPEUNUSED,
3604                      message ("Type %q declared but not used", 
3605                               uentry_getName (ce)),
3606                      fwhere);
3607                 }
3608             }
3609           else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3610             { /* errors for ref params will be reported in the next scope */
3611               llassertprint (uentry_isVar (ce), 
3612                              ("ce: %s", uentry_unparseFull (ce)));
3613
3614               if (ctype_isFunction (uentry_getType (ce)))
3615                 {
3616                   if (fileloc_isUser (fwhere))
3617                     {
3618                       hasError = optgenerror
3619                         (FLG_FUNCUNUSED,
3620                          message ("%q %q declared but not used", 
3621                                   cstring_makeLiteral 
3622                                   (isFileStatic ? "File static function" 
3623                                    : "Function"),
3624                                   uentry_getName (ce)),
3625                          fwhere);
3626                     }
3627                 }
3628               else 
3629                 {
3630                   if (fileloc_isUser (fwhere))
3631                     {
3632                       
3633                       
3634                       hasError = optgenerror 
3635                         (FLG_VARUNUSED,
3636                          message ("%q %q declared but not used", 
3637                                   cstring_makeLiteral 
3638                                   (isFileStatic ? "File static variable" 
3639                                    : "Variable"), 
3640                                   uentry_getName (ce)),
3641                          fwhere);
3642                     }
3643                 }
3644             }
3645           else
3646             {
3647               ; /* no errors */
3648             }
3649         } /* unused */
3650       else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3651         { /* check all fields */
3652           ctype ct = uentry_getRealType (ce); 
3653
3654           
3655           while (ctype_isAP (ct))
3656             {
3657               ct = ctype_getBaseType (ct);
3658             }
3659
3660           if (ctype_isSU (ct))
3661             {
3662               uentryList fields = ctype_getFields (ct);
3663
3664               uentryList_elements (fields, field)
3665                 {
3666                   if (!uentry_isUsed (field))
3667                     {
3668                       if (uentry_hasName (ce))
3669                         {
3670                           hasError |= optgenerror 
3671                             (FLG_FIELDUNUSED,
3672                              message ("Field %q of %s %q declared but not used", 
3673                                       uentry_getName (field),
3674                                       cstring_makeLiteralTemp
3675                                       (ctype_isStruct (ct) ? "structure" : "union"),
3676                                       uentry_getName (ce)),
3677                              uentry_whereEarliest (field));
3678                         }
3679                       else
3680                         {
3681                           /*
3682                           ** evans 2001-06-08
3683                           ** Can't report these errors for unnamed structs.
3684                           ** No way to tell when there are multiple consistent
3685                           ** unnamed structure types.  (Could go through table
3686                           ** and mark them all unused...)
3687
3688                           hasError |= optgenerror 
3689                             (FLG_FIELDUNUSED,
3690                              message ("Field %q of unnamed %s declared but not used", 
3691                                       uentry_getName (field),
3692                                       cstring_makeLiteralTemp
3693                                       (ctype_isStruct (ct) ? "structure" : "union")),
3694                              uentry_whereEarliest (field));
3695
3696                           */
3697                         }
3698                       
3699                       uentry_setUsed (field, fileloc_undefined);
3700                     }
3701                 } end_uentryList_elements;
3702             }
3703         }
3704       else
3705         {
3706           ; /* no errors */
3707         }
3708
3709       if (hasError)
3710         {
3711           if (uentry_isParam (ce) && context_inMacro ())
3712             {
3713               if (fileloc_isDefined (uentry_whereSpecified (ce)))
3714                 {
3715                   uentry_showWhereSpecified (ce);
3716                 }
3717             }
3718           else
3719             {
3720               uentry_showDefSpecInfo (ce, fwhere);
3721             }
3722
3723           uentry_setUsed (ce, fileloc_undefined);
3724         }
3725     }
3726 }
3727
3728 static void
3729 checkGlobalReturn (uentry glob, sRef orig)
3730 {
3731   sRef sr = uentry_getSref (glob);
3732   
3733   DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3734             uentry_unparseFull (glob),
3735             sRef_unparseFull (orig),
3736             sRef_unparseFull (sr)));
3737
3738   DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3739
3740   if (context_getFlag (FLG_GLOBSTATE))
3741     {
3742       DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3743       
3744       if (sRef_isKilledGlob (orig))
3745         {
3746           if (sRef_isStateUndefined (sr)
3747               || sRef_isUnuseable (sr)
3748               || sRef_isStateUnknown (sr)
3749               || sRef_isDead (sr))
3750             {
3751               ;
3752             }
3753           else
3754             {
3755               ctype ct = ctype_realType (uentry_getType (glob));
3756               
3757               DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3758
3759               if (ctype_isVisiblySharable (ct))
3760                 {
3761                   if (optgenerror 
3762                       (FLG_GLOBSTATE,
3763                        message 
3764                        ("Killed global %q (type %s) not released before return",
3765                         uentry_getName (glob),
3766                         ctype_unparse (ct)),
3767                        g_currentloc))
3768                     {
3769                       sRef_showStateInfo (sr);
3770                     }
3771                 }
3772               else
3773                 {
3774                   sRef_protectDerivs ();
3775                   (void) transferChecks_globalDestroyed (sr, g_currentloc);
3776                   sRef_clearProtectDerivs ();
3777                 }
3778             }
3779         }
3780       else
3781         {
3782           if (sRef_isStateUndefined (sr))
3783             {
3784               if (optgenerror (FLG_GLOBSTATE,
3785                                message 
3786                                ("Function returns with global %q undefined",
3787                                 uentry_getName (glob)),
3788                                g_currentloc))
3789                 {
3790                   sRef_showStateInfo (sr);
3791                 }
3792             }
3793           else 
3794             {
3795               if (sRef_isDead (sr) || sRef_isKept (sr))
3796                 {
3797                   if (optgenerror 
3798                       (FLG_GLOBSTATE,
3799                        message ("Function returns with global %q "
3800                                 "referencing %s storage",
3801                                 uentry_getName (glob),
3802                                 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3803                        g_currentloc))
3804                     {
3805                       if (sRef_isKept (sr))
3806                         {
3807                           sRef_showAliasInfo (sr);      
3808                         }
3809                       else
3810                         {
3811                           sRef_showStateInfo (sr);
3812                         }
3813
3814                       sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3815                     }
3816                 }
3817               
3818               if (ctype_isRealPointer (uentry_getType (glob))
3819                   && sRef_possiblyNull (sr)
3820                   && !uentry_possiblyNull (glob))
3821                 {
3822                   if (optgenerror 
3823                       (FLG_GLOBSTATE,
3824                        message ("Function returns with non-null global %q "
3825                                 "referencing null storage",
3826                                 uentry_getName (glob)),
3827                        g_currentloc))
3828                     {
3829                       sRef_showNullInfo (sr);
3830                     }
3831                 }
3832               else
3833                 {
3834                   DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3835                   transferChecks_globalReturn (glob);
3836                 }
3837             }
3838         }
3839     }
3840 }
3841
3842 /*
3843 ** remember: check alias globals
3844 */
3845
3846 void usymtab_checkFinalScope (bool isReturn)
3847   /*@globals utab@*/
3848 {
3849   bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3850   sRefSet checked = sRefSet_new ();
3851   usymtab stab = utab;
3852   int i;
3853     
3854   /*
3855   ** need to check all scopes out to function parameters.
3856   */
3857
3858   do 
3859     {
3860       for (i = 0; i < stab->nentries; i++)
3861         {
3862           uentry ce = stab->entries[i];
3863           sRef sr = uentry_getSref (ce);
3864           sRef rb = sRef_getRootBase (sr);
3865           valueTable tvalues;
3866
3867           /*
3868           ** Shouldn't check if shadow checked in deeper scope:
3869           */
3870
3871           if (stab != utab)
3872             {
3873               uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3874
3875               if (!uentry_sameObject (ce, oue))
3876                 {
3877                   /* what if it is one an alternate branch? */
3878                   /*@innercontinue@*/ continue;
3879                 }
3880             }
3881           
3882           DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3883           
3884           if (ctype_isFunction (uentry_getType (ce)))
3885             {
3886               /*@innercontinue@*/ continue;
3887             }
3888
3889           if (uentry_isAnyParam (ce)
3890               || uentry_isRefParam (ce)
3891               || sRef_isFileOrGlobalScope (rb))
3892             {
3893               /* Don't do the loseref check...but should check state! */
3894               DPRINTF (("Skipping check 1"));
3895             }
3896           else if (sRef_isDefinitelyNull (sr)
3897                    || usymtab_isDefinitelyNull (sr))
3898             {
3899               /*
3900               ** No state reference errors for definitely null references.
3901               */
3902
3903               DPRINTF (("Skipping check 2"));
3904             }
3905           else
3906             {
3907               DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce), 
3908                         sRef_unparseFull (sr)));
3909               
3910               tvalues = sRef_getValueTable (sr);
3911               
3912               valueTable_elements (tvalues, fkey, fval) {
3913                 metaStateInfo minfo;
3914                 cstring msg = cstring_undefined;
3915                 int nval;
3916                 
3917                 minfo = context_lookupMetaStateInfo (fkey);
3918                 llassert (metaStateInfo_isDefined (minfo));
3919                 
3920                 if (stateValue_isError (fval)
3921                     || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3922                   {
3923                     DPRINTF (("Skipping check 3"));
3924                   }
3925                 else 
3926                   {
3927                     DPRINTF (("Check: %s / %s / %s", fkey,
3928                               metaStateInfo_unparse (minfo),
3929                               stateValue_unparse (fval)));
3930                     
3931                     minfo = context_lookupMetaStateInfo (fkey);
3932                     
3933                     nval = stateCombinationTable_lookupLoseReference 
3934                       (metaStateInfo_getTransferTable (minfo), 
3935                        stateValue_getValue (fval), &msg);
3936                     
3937                     if (cstring_isDefined (msg)) 
3938                       {
3939                         if (optgenerror 
3940                             (FLG_STATETRANSFER,
3941                              message
3942                              ("%s loses reference %q in invalid state %q (%s)",
3943                               cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3944                               uentry_getName (ce),
3945                               stateValue_unparseValue (fval, minfo),
3946                               msg),
3947                              g_currentloc))
3948                           {
3949                             stateValue_show (fval, minfo);
3950                           }
3951                         else
3952                           {
3953                             DPRINTF (("Suppressed transfer error: %s", msg));
3954                           }
3955                       }
3956                   }
3957               } end_valueTable_elements;
3958             }
3959
3960           DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3961           
3962           if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3963             {
3964               if (ctype_isRealSU (uentry_getType (ce))
3965                   && !uentry_isAnyParam (ce)
3966                   && !uentry_isRefParam (ce)
3967                   && !uentry_isStatic (ce)
3968                   && !sRef_isDependent (sr)
3969                   && !sRef_isOwned (sr))
3970                 {
3971                   sRefSet als = usymtab_allAliases (sr);
3972                   
3973                   if (sRefSet_isEmpty (als))
3974                     {
3975                       transferChecks_localDestroyed (sr, g_currentloc);
3976                     }
3977                   else
3978                     {
3979                       /* aliased, no problem */ ;
3980                     }
3981                   
3982                   sRefSet_free (als);
3983                 }
3984               else if
3985                 (!uentry_isStatic (ce)
3986                  && ((sRef_isNewRef (sr))
3987                      || (((sRef_isOnly (sr) || sRef_isFresh (sr) 
3988                            || sRef_isKeep (sr) || sRef_isOwned (sr))
3989                           && !sRef_isDead (sr))
3990                          && (!sRef_definitelyNull (sr))
3991                          && (!usymtab_isDefinitelyNull (sr)))))
3992                 {
3993                   bool hasError = TRUE;
3994                   
3995                   DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3996                   
3997                   /*
3998                   ** If its a scope exit, check if there is an alias.
3999                   ** If so, make it only.  If not, there is an error.
4000                   */
4001                   
4002                   if (!isReturn)
4003                     {
4004                       if (transferChecks_canLoseReference (sr, g_currentloc))
4005                         {
4006                           DPRINTF (("Can lose!"));
4007                           hasError = FALSE;
4008                         }
4009                     }
4010                   
4011                   if (hasError)
4012                     {
4013                       if (sRef_hasLastReference (sr))
4014                         {
4015                           sRef ar = sRef_getAliasInfoRef (sr);
4016                           
4017                           if (optgenerror 
4018                               (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4019                                message
4020                                ("Last reference %q to %s storage %qnot %q before %q",
4021                                 sRef_unparse (sr),
4022                                 alkind_unparse (sRef_getAliasKind (sr)),
4023                                 sRef_unparseOpt (ar),
4024                                 cstring_makeLiteral (sRef_isKeep (sr) 
4025                                                      ? "transferred" : "released"),
4026                                 cstring_makeLiteral (isReturn 
4027                                                      ? "return" : "scope exit")),
4028                                g_currentloc))
4029                             {
4030                               sRef_showRefLost (sr);
4031                             }
4032                         }
4033                       else if (sRef_isNewRef (sr))
4034                         {
4035                           if (optgenerror
4036                               (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4037                                message 
4038                                ("%q %q not released before %q",
4039                                 cstring_makeLiteral 
4040                                 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4041                                  ? "Kill reference parameter" : "New reference"),
4042                                 uentry_getName (ce),
4043                                 cstring_makeLiteral (isReturn
4044                                                      ? "return" : "scope exit")),
4045                                g_currentloc))
4046                             {
4047                               sRef_showAliasInfo (sr);
4048                             }
4049                         }
4050                       else 
4051                         {
4052                           if (ctype_isRealSU (sRef_getType (sr)))
4053                             {
4054                               transferChecks_structDestroyed (sr, g_currentloc);
4055                             }
4056                           else
4057                             {
4058                               if (optgenerror
4059                                   (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4060                                    message 
4061                                    ("%s storage %q not %q before %q",
4062                                     alkind_capName (sRef_getAliasKind (sr)),
4063                                     uentry_getName (ce),
4064                                     cstring_makeLiteral (sRef_isKeep (sr) 
4065                                                          ? "transferred" : "released"),
4066                                     cstring_makeLiteral (isReturn 
4067                                                          ? "return" : "scope exit")),
4068                                    g_currentloc))
4069                                 {
4070                                   sRef_showAliasInfo (sr);
4071                                   DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4072                                 }
4073                             }
4074                         }
4075                     }
4076                 }
4077               else
4078                 {
4079                   ;
4080                 }
4081             }
4082
4083           if (mustDefine && uentry_isOut (ce))
4084             {
4085               /* No error if its dead (either only or error already reported */
4086               if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4087                 {
4088                   voptgenerror 
4089                     (FLG_MUSTDEFINE,
4090                      message ("Out storage %q not defined before %q",
4091                               uentry_getName (ce),
4092                               cstring_makeLiteral 
4093                               (isReturn ? "return" : "scope exit")),
4094                      g_currentloc);
4095
4096                   DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4097                 }
4098             }
4099           
4100           /*
4101           ** also check state is okay
4102           */
4103           
4104           if (usymtab_lexicalLevel () > functionScope
4105               && uentry_isVariable (ce)
4106               && (sRef_isLocalVar (sr)
4107                   && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4108             {
4109               sRefSet ab = usymtab_aliasedBy (sr);
4110               
4111               /* should do something more efficient here */
4112               
4113               if (sRefSet_isEmpty (ab))
4114                 {
4115                   /* and no local ref */
4116                   DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4117                   transferChecks_loseReference (ce);
4118                 }
4119               else
4120                 {
4121                   ;
4122                 }
4123               
4124               sRefSet_free (ab);
4125             }
4126           else 
4127             {
4128               ;
4129             }
4130           
4131           checked = sRefSet_insert (checked, sr);
4132         }
4133
4134       llassert (usymtab_isDefined (stab->env));
4135
4136       if (usymtab_isBranch (stab))
4137         {
4138           stab = usymtab_dropEnv (stab);
4139         }
4140       else
4141         {
4142           stab = stab->env;
4143         }
4144       
4145       llassert (stab != usymtab_undefined);
4146     } while (isReturn && (stab->lexlevel >= paramsScope));
4147   
4148   sRefSet_free (checked);
4149   
4150   /*
4151   ** for returns:
4152   **      all globals are appropriately defined
4153   **      all parameters are appropriately defined
4154   **      special clauses are followed
4155   */
4156
4157   if (isReturn || (utab->lexlevel == paramsScope))
4158     {
4159       uentry fcn = context_getHeader ();
4160       uentryList params = context_getParams ();
4161       globSet uglobs = context_getUsedGlobs ();
4162       globSet sglobs = context_getGlobs ();
4163             
4164       if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4165         { 
4166           aliasTable_checkGlobs (utab->aliases); 
4167         }
4168
4169       /*
4170       ** state clauses (ensures, defines, sets, allocates, releases) 
4171       */
4172       
4173       if (uentry_hasStateClauseList (fcn))
4174         {
4175           stateClauseList clauses = uentry_getStateClauseList (fcn);
4176
4177           stateClauseList_elements (clauses, cl)
4178             {
4179               if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl)) 
4180                 { 
4181                   if (stateClause_setsMetaState (cl)) 
4182                     {
4183                       sRefSet rfs = stateClause_getRefs (cl);
4184                       qual q = stateClause_getMetaQual (cl);
4185                       annotationInfo ainfo = qual_getAnnotationInfo (q);
4186                       metaStateInfo minfo = annotationInfo_getState (ainfo);
4187                       cstring key = metaStateInfo_getName (minfo);
4188                       int mvalue = annotationInfo_getValue (ainfo);
4189
4190                       DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4191
4192                       sRefSet_elements (rfs, el)
4193                         {
4194                           sRef base = sRef_getRootBase (el);
4195                           
4196                           if (sRef_isResult (base))
4197                             {
4198                               /* 
4199                               ** This is checked for return transfers. 
4200                               */
4201                               ;
4202                             }
4203                           else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4204                             {
4205                               sRef sr = sRef_updateSref (base);
4206                               sr = sRef_fixBase (el, sr);
4207                               
4208                               if (!sRef_checkMetaStateValue (sr, key, mvalue))
4209                                 {
4210                                   if (optgenerror 
4211                                       (FLG_STATETRANSFER,
4212                                        message
4213                                        ("Ensures clause not satisfied%q (state is %q): %q",
4214                                         sRef_isGlobalMarker (sr) 
4215                                         ? message ("") 
4216                                         : message (" by %q", sRef_unparse (sr)),
4217                                         stateValue_unparseValue (sRef_getMetaStateValue (sr, key), 
4218                                                                  minfo),
4219                                         stateClause_unparse (cl)),
4220                                        g_currentloc))
4221                                     {
4222                                       sRef_showMetaStateInfo (sr, key);
4223                                     }  
4224                                 }
4225                             }
4226                           else
4227                             {
4228                               if (sRef_isMeaningful (el))
4229                                 {
4230                                   BADBRANCH;
4231                                 }
4232                             }
4233                         } end_sRefSet_elements ;
4234                     }
4235                   else
4236                     {
4237                       /* evs - 2000 07 10 - added this */
4238                       sRefTest tst = stateClause_getPostTestFunction (cl);
4239                       sRefSet rfs = stateClause_getRefs (cl);
4240                       
4241                       sRefSet_elements (rfs, el)
4242                         {
4243                           sRef base = sRef_getRootBase (el);
4244                           
4245                           if (sRef_isResult (base))
4246                             {
4247                               /* 
4248                               ** This is checked for return transfers. 
4249                               */
4250
4251                               ; 
4252                             }
4253                           else if (sRef_isParam (base))
4254                             {
4255                               sRef sr = sRef_updateSref (base);
4256                               sr = sRef_fixBase (el, sr);
4257                               
4258                               if (tst != NULL && !tst (sr))
4259                                 {
4260                                   if (optgenerror 
4261                                       (stateClause_postErrorCode (cl),
4262                                        message ("%s storage %qcorresponds to "
4263                                                 "storage listed in %q clause",
4264                                                 stateClause_postErrorString (cl, sr),
4265                                                 sRef_unparseOpt (sr),
4266                                                 stateClause_unparseKind (cl)),
4267                                        g_currentloc))
4268                                     {
4269                                       sRefShower ss = stateClause_getPostTestShower (cl);
4270                                       
4271                                       if (ss != NULL)
4272                                         {
4273                                           ss (sr);
4274                                         }
4275                                       
4276                                       DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4277                                     }  
4278                                 }
4279                             }
4280                           else
4281                             {
4282                               if (sRef_isMeaningful (el))
4283                                 {
4284                                   BADBRANCH;
4285                                 }
4286                             }
4287                         } end_sRefSet_elements ;
4288                     }
4289                 }
4290             } end_stateClauseList_elements ;
4291         }
4292       
4293       /*
4294       ** check parameters on return
4295       */
4296
4297       uentryList_elements (params, arg)
4298         {
4299           if (!uentry_isElipsisMarker (arg))
4300             {
4301               ctype rt = ctype_realType (uentry_getType (arg));
4302
4303               if (ctype_isMutable (rt) || ctype_isSU (rt))
4304                 {
4305                   uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4306                   DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4307                   transferChecks_paramReturn (param);
4308                 }
4309             }
4310         } end_uentryList_elements;
4311       
4312       DPRINTF (("Check global return: %s",
4313                 globSet_unparse (sglobs)));
4314
4315       globSet_allElements (sglobs, el)
4316         {
4317           sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4318           uentry current = sRef_getUentry (el);
4319
4320           DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4321                     uentry_unparseFull (current)));
4322           
4323           if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4324             {
4325               checkGlobalReturn (current, orig);
4326             }
4327         } end_globSet_allElements;
4328
4329       globSet_allElements (uglobs, el)
4330         {
4331           if (!globSet_member (sglobs, el))
4332             {
4333               uentry current = sRef_getUentry (el);
4334               
4335               if (uentry_isVariable (current)
4336                   && !uentry_isRealFunction (current))
4337                 {
4338                   checkGlobalReturn (current, sRef_undefined);
4339                 }
4340             }
4341         } end_globSet_allElements;
4342     }  
4343 }
4344
4345 void
4346 usymtab_quietExitScope (fileloc loc) 
4347    /*@globals utab, globtab, filetab; @*/ 
4348    /*@modifies utab@*/
4349 {
4350   usymtab t = utab->env;
4351
4352   DPRINTF (("Quiet exit scope [%p]", utab));
4353
4354   if (utab->reftable != NULL)
4355     {
4356       int i;
4357
4358       for (i = 0; i < utab->nentries; i++)
4359         {
4360           uentry current = utab->entries[i];      
4361           uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4362
4363           uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4364         }
4365     }
4366
4367   llassert (t != NULL);
4368
4369   if (t->lexlevel > paramsScope)
4370     {
4371       t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4372       t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases, 
4373                                              t->lexlevel);
4374       utab->aliases = aliasTable_undefined;
4375     }
4376
4377   t->mustBreak = utab->mustBreak;
4378   t->exitCode = utab->exitCode;
4379
4380   DPRINTF (("Free level [%p]", utab));
4381   usymtab_freeLevel (utab);
4382
4383   utab = t;
4384
4385 # ifdef DEBUGSPLINT
4386   usymtab_checkAllValid ();
4387 # endif
4388 }
4389
4390 /*
4391 ** Exit a scope with no checking, lose alias states.
4392 ** (When should this be used?)
4393 */
4394
4395 void usymtab_quietPlainExitScope (void)
4396      /*@globals utab, globtab, filetab@*/
4397      /*@modifies utab@*/
4398 {
4399   usymtab t = utab->env;
4400
4401   llassert (t != NULL);
4402   llassert (NOALIAS (utab->aliases, t->aliases));
4403   usymtab_freeLevel (utab);
4404   utab = t;
4405 }
4406
4407 void usymtab_exitScope (exprNode expr)
4408   /*@globals utab, filetab, globtab@*/
4409   /*@modifies utab, globtab@*/
4410 {
4411   usymtab ctab = usymtab_undefined;
4412   usymtab lctab = usymtab_undefined;
4413   bool mustReturn = exprNode_mustEscape (expr);
4414
4415   DPRINTF (("Exit scope [%p]", utab));
4416
4417   if (utab->kind == US_CBRANCH)
4418     {
4419       /*
4420       ** save the case branches, remove the first non-cbranch
4421       */
4422
4423       ctab = utab;
4424
4425       while (utab->kind == US_CBRANCH) 
4426         {
4427           lctab = utab;
4428           utab = utab->env;
4429           llassert (utab != GLOBAL_ENV);
4430         }
4431     }
4432   
4433   if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4434       || utab->kind == US_CBRANCH || utab->kind == US_SWITCH) 
4435     {
4436       if (context_inMacro ()) 
4437         {
4438           /* evs 2000-07-25 */
4439           /* Unparseable macro may end inside nested scope.  Deal with it. */
4440           
4441           llerror (FLG_SYNTAX, 
4442                    message ("Problem parsing macro body of %s (unbalanced scopes). "
4443                             "Attempting to recover, recommend /*@notfunction@*/ before "
4444                             "macro definition.", 
4445                             context_inFunctionName ()));
4446           
4447           while (utab->kind == US_TBRANCH
4448                  || utab->kind == US_FBRANCH
4449                  || utab->kind == US_CBRANCH
4450                  || utab->kind == US_SWITCH) 
4451             {
4452               utab = utab->env;
4453               llassert (utab != GLOBAL_ENV);
4454             }
4455         } else 
4456           {
4457             llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4458             /*@-branchstate@*/ 
4459           } /*@=branchstate@*/
4460     }
4461   
4462   /*
4463   ** check all variables in scope were used
4464   */
4465
4466   /*
4467   ** bogus errors if this is the normal inside a switch,
4468   ** since cases have not been merged yet.  Should probably
4469   ** still check this, but I'm too lazy at the moment...
4470   */
4471
4472   llassertfatal (utab->env != GLOBAL_ENV);
4473
4474   if (utab->env->kind != US_SWITCH)
4475     {
4476       usymtab_allUsed ();
4477     }
4478
4479   /*
4480   ** check aliasing: all only params are released (dead)
4481   **     definition: all out params are defined, all modified params 
4482   **                     are completely defined
4483   **
4484   ** NOTE: note for exiting paramsScope, since checkReturn should be
4485   ** called first.
4486   */
4487   
4488   if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4489     {
4490       /*
4491       ** should only call this is end of scope is reachable...
4492       */
4493
4494       usymtab_checkFinalScope (FALSE);
4495     }
4496
4497   if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4498     {
4499       /*
4500       ** leaving a function, need to fix up globals
4501       */
4502
4503       uentryList params = context_getParams ();
4504       globSet    globs = context_getUsedGlobs ();
4505
4506       uentryList_elements (params, ue)
4507         {
4508           uentry_fixupSref (ue);
4509         } end_uentryList_elements;
4510
4511       clearFunctionTypes ();
4512
4513       DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4514
4515       globSet_allElements (globs, el)
4516         {
4517           DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4518
4519           if (sRef_isCvar (el))
4520             {
4521               uentry current;
4522               usymId index = sRef_getScopeIndex (el);
4523               
4524               if (sRef_isFileStatic (el))
4525                 {
4526                   llassert (usymtab_isDefined (filetab));
4527                   current = usymtab_fetchIndex (filetab, index);
4528                 }
4529               else
4530                 {
4531                   current = usymtab_fetchIndex (globtab, index);
4532                 }
4533               
4534               if (uentry_isVariable (current))
4535                 {
4536                   DPRINTF (("Fixup: %s", uentry_unparse (current)));
4537                   uentry_fixupSref (current);
4538                 }
4539               else
4540                 {
4541                   DPRINTF (("Clear: %s", uentry_getSref (current)));
4542                   sRef_clearDerived (uentry_getSref (current));
4543                 }
4544             }
4545
4546           sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4547         } end_globSet_allElements;
4548     }
4549   
4550   usymtab_quietExitScope (exprNode_loc (expr));
4551   
4552   if (lctab != usymtab_undefined)
4553     {
4554       /*@i@*/ lctab->env = utab;  
4555       /*@i@*/ utab = ctab;
4556     /*@-branchstate@*/ } /*@=branchstate@*/
4557   /*@-globstate@*/
4558
4559
4560 # ifdef DEBUGSPLINT
4561   usymtab_checkAllValid ();
4562 # endif
4563 }
4564 /*@=globstate@*/
4565
4566 /*
4567 ** yikes!  don't let the '170 kids see this one...
4568 */
4569
4570 usymId
4571 usymtab_directParamNo (uentry ue)
4572 {
4573   if (uentry_isVar (ue))
4574     {
4575       sRef sr = uentry_getSref (ue);
4576
4577       if (sRef_lexLevel (sr) == functionScope)
4578         {
4579           usymId index = sRef_getScopeIndex (sr);
4580
4581           if (index < usymId_fromInt (uentryList_size (context_getParams ())))
4582             {
4583               return index;
4584             }
4585         }
4586     }
4587   return usymId_invalid;
4588 }
4589
4590 /*@dependent@*/ /*@exposed@*/ uentry
4591   usymtab_getParam (int paramno)
4592   /*@globals utab@*/
4593 {
4594   /*
4595   ** requires in a function context (checked)
4596   **
4597   ** depends on no nested functions --- the function
4598   ** parameters are ALWAYS one scope inside the global scope
4599   ** and entered in order!
4600   */
4601   usymtab s = utab;
4602
4603   if (!context_inFunctionLike ())
4604     llfatalbug (message ("usymtab_getParam: not in function context: %q", 
4605                          context_unparse ()));
4606
4607   while (s->lexlevel > paramsScope) 
4608     {
4609       s = s->env;
4610     }
4611
4612   llassert (usymtab_isDefined (s));
4613
4614   if (paramno >= s->nentries)
4615     {
4616       /*  
4617       ** Parse errors lead to this. 
4618       */
4619
4620       uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4621                                            ctype_unknown);
4622       
4623       uentry_markOwned (err);
4624       return (err);
4625     }
4626
4627   return (s->entries[paramno]);
4628 }
4629
4630 static /*@dependent@*/ /*@exposed@*/ uentry 
4631 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4632 {
4633   uentry ue;
4634
4635   ue = usymtab_getRefNoisy (u, level, index);
4636
4637   if (uentry_isUndefined (ue))
4638     {
4639       llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4640                     index, level));
4641     }
4642   
4643   return ue;
4644 }
4645
4646 static /*@dependent@*/ /*@exposed@*/ usymtab 
4647   usymtab_dropEnv (/*@notnull@*/ usymtab s)
4648 {
4649   if (s->kind == US_CBRANCH)
4650     {
4651       usymtab t = s;
4652
4653       do 
4654         {
4655           t = s;
4656           s = s->env;
4657           llassert (s != GLOBAL_ENV);
4658         } while (s->kind == US_CBRANCH); 
4659       /* drop all cases (except in nested scopes */ 
4660
4661       s = t;
4662       llassert (s != GLOBAL_ENV);
4663     }
4664
4665   if (s->kind == US_FBRANCH)
4666     {
4667       s = s->env; /* skip the true branch */
4668       llassert (usymtab_isDefined (s));
4669       llassert (s->kind == US_TBRANCH);
4670     }
4671
4672   llassert (s != GLOBAL_ENV);
4673   s = s->env;
4674
4675   return s;
4676 }
4677
4678 /*@dependent@*/ /*@exposed@*/ uentry
4679   usymtab_getRefQuiet (int level, usymId index)
4680   /*@globals utab@*/
4681 {
4682   usymtab s = utab;
4683   
4684   
4685   llassert (s != NULL);
4686   llassert (index >= 0);
4687
4688   if (level > s->lexlevel)
4689     {            
4690       return uentry_undefined;
4691     }
4692
4693   llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d", 
4694                                         level, s->lexlevel)); 
4695
4696   while (s->lexlevel > level)
4697     {
4698       if (usymtab_isBranch (s))
4699         {
4700           int eindex = refTable_lookup (s, level, index);
4701
4702           if (eindex != NOT_FOUND)
4703             {
4704               return (s->entries[eindex]);
4705             }
4706         }
4707
4708       s = usymtab_dropEnv (s);
4709     }
4710
4711   while (usymtab_isBranch (s) && s->lexlevel == level)
4712     {
4713       int eindex = refTable_lookup (s, level, index);
4714       
4715       if (eindex != NOT_FOUND)
4716         {
4717           return (s->entries[eindex]);
4718         }
4719
4720       s = usymtab_dropEnv (s);
4721     }
4722  
4723   if (index >= usymId_fromInt (s->nentries))
4724     {
4725       return uentry_undefined;
4726     }
4727
4728   llassert (!uentry_isUndefined (s->entries[index]));
4729
4730   return s->entries[index];
4731 }
4732
4733 static /*@dependent@*/ /*@exposed@*/ uentry
4734 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4735 {
4736   usymtab otab = s;
4737   uentry ue = uentry_undefined;
4738   
4739   llassert (index >= 0);
4740   
4741   while (s->lexlevel > level)
4742     {
4743       if (usymtab_isBranch (s))
4744         {
4745           int eindex = refTable_lookup (s, level, index);
4746
4747           if (eindex != NOT_FOUND)
4748             {
4749               ue = s->entries[eindex];
4750
4751               if (s != otab)
4752                 {
4753                   while (!usymtab_isBranch (otab))
4754                     {
4755                       otab = usymtab_dropEnv (otab);
4756                       llassert (otab != GLOBAL_ENV);
4757                     }
4758                 
4759                   if (refTable_lookup (otab, level, index) == NOT_FOUND)
4760                     {
4761                       ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4762                     }
4763                   else
4764                     {
4765                       ;
4766                     }
4767                 }
4768               
4769               return ue;
4770             }
4771         }
4772
4773       s = usymtab_dropEnv (s);
4774     }
4775
4776   llassert (usymtab_isDefined (s));
4777
4778   while (usymtab_isBranch (s) && s->lexlevel == level)
4779     {
4780       int eindex = refTable_lookup (s, level, index);
4781       
4782       if (eindex != NOT_FOUND)
4783         {
4784           ue = s->entries[eindex];
4785           
4786           if (s != otab)
4787             {
4788               while (!usymtab_isBranch (otab))
4789                 {
4790                   otab = usymtab_dropEnv (otab);
4791                   llassert (otab != GLOBAL_ENV);
4792                 }
4793
4794               ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4795             }
4796           else
4797             {
4798               ;
4799             } 
4800
4801           return ue;
4802         }
4803
4804       s = usymtab_dropEnv (s);
4805           }
4806
4807   if (s->lexlevel == level && (index < usymId_fromInt (s->nentries)))
4808     {
4809       ue = s->entries[index];
4810       
4811       if (uentry_isValid (ue))
4812         {
4813           if (s != otab)
4814             {
4815               while (!usymtab_isBranch (otab))
4816                 {
4817                   otab = usymtab_dropEnv (otab);
4818                   
4819                   if (otab == GLOBAL_ENV)
4820                     {
4821                       return ue;
4822                     }
4823                 }
4824               
4825               ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4826             }
4827           else
4828             {
4829             }
4830         }
4831       
4832       return ue;
4833     }
4834
4835   
4836   if (index >= usymId_fromInt (s->nentries))
4837     {
4838       return uentry_undefined;
4839     }
4840
4841   llassert (!uentry_isUndefined (s->entries[index]));
4842
4843   return s->entries[index];
4844 }
4845
4846 /*
4847 ** looking up entries
4848 **
4849 ** If entry is inside a branch, then copy it, and put it into 
4850 ** the branch table.
4851 */
4852
4853 static
4854 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, usymId index)
4855 {
4856   refTable rt = ut->reftable;
4857   int i;
4858
4859   llassert (rt != NULL);
4860
4861   for (i = 0; i < ut->nentries; i++)
4862     {
4863       if (rt[i]->level == level && rt[i]->index == usymId_toInt (index))
4864         {
4865           return i;
4866         }
4867     }
4868   
4869   return NOT_FOUND;
4870 }
4871   
4872 static
4873 /*@only@*/ refentry refentry_create (int level, int index)
4874 {
4875   refentry r = (refentry) dmalloc (sizeof (*r));
4876
4877   r->level = level;
4878   r->index = index;
4879
4880   return r;
4881 }
4882
4883 static /*@dependent@*/ /*@exposed@*/ uentry
4884 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4885 {
4886   usymtab ut = s;
4887
4888   if (ut->reftable == NULL) 
4889     {
4890       DPRINTF (("Adding ref entry without reftable: %s", k));
4891       return uentry_undefined;
4892     }
4893
4894   llassert (ut->reftable != NULL);
4895   
4896   while (s != GLOBAL_ENV)
4897     {
4898       usymId eindex = usymtab_getIndex (s, k);
4899       
4900       if (usymtab_indexFound (eindex))
4901         {
4902           uentry current = s->entries[eindex];
4903
4904           if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4905             {
4906               uentry ue;
4907
4908               DPRINTF (("Here: copying %s", uentry_unparse (current)));
4909               if (uentry_isNonLocal (current))
4910                 {
4911                   ue = uentry_copy (current);
4912                 }
4913               else
4914                 {
4915                   ue = uentry_copyNoSave (current);
4916                 }
4917
4918               DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4919               usymtab_addEntryQuiet (ut, ue);
4920               DPRINTF (("Okay..."));
4921               
4922               if (s->reftable != NULL)
4923                 {
4924                   refentry ref = s->reftable[eindex];
4925                   
4926                   ut->reftable[ut->nentries - 1] 
4927                     = refentry_create (ref->level, ref->index);
4928                 }
4929               else
4930                 {
4931                   ut->reftable[ut->nentries - 1] 
4932                     = refentry_create (s->lexlevel, usymId_toInt (eindex));
4933                 }
4934               
4935               return (ue);
4936             }
4937           else
4938             {
4939               return (current);
4940             }
4941         }
4942
4943       s = usymtab_dropEnv (s);
4944     }
4945
4946   return uentry_undefined;
4947 }
4948
4949 static uentry usymtab_lookupAux (usymtab s, cstring k)
4950 {
4951   DPRINTF (("Lookup: %s", k));
4952
4953   while (s != GLOBAL_ENV)
4954     {
4955       usymId eindex = usymtab_getIndex (s, k);
4956
4957       if (usymtab_indexFound (eindex))
4958         {
4959           uentry ret = s->entries[eindex];
4960 # if 0    
4961
4962           
4963           if (s->kind == US_TBRANCH 
4964               || s->kind == US_FBRANCH
4965               || s->kind == US_CBRANCH)
4966               /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4967             {
4968               uentry ret;
4969               DPRINTF (("Adding global ref entry: %s", k));
4970               ret = usymtab_addRefEntry (os, k);
4971               DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4972               return ret;
4973             }
4974
4975 # endif
4976           DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4977           return (ret);
4978         }
4979       
4980       if (s->kind == US_TBRANCH || s->kind == US_FBRANCH 
4981           || s->kind == US_CBRANCH)
4982         {
4983           /* why isn't this os??? */
4984           uentry ret = usymtab_addRefEntry (s, k);
4985           DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4986           return ret;
4987         }
4988       
4989       s = s->env;
4990     }
4991   
4992   return uentry_undefined;
4993 }
4994
4995 static /*@dependent@*/ /*@exposed@*/ uentry
4996 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
4997 {
4998   while (s != GLOBAL_ENV)
4999     {
5000       usymId eindex = usymtab_getIndex (s, k);
5001       
5002       if (usymtab_indexFound (eindex))
5003         {
5004           uentry ret = s->entries[eindex];
5005           return (ret);
5006         }
5007       
5008       if (noalt && usymtab_isBranch (s))
5009         {
5010           s = usymtab_dropEnv (s);
5011         }
5012       else
5013         {
5014           llassert (s != NULL); 
5015           s = s->env;
5016         }
5017     }
5018
5019   return uentry_undefined;
5020 }
5021
5022 static /*@exposed@*/ /*@dependent@*/ uentry 
5023 usymtab_lookupQuiet (usymtab s, cstring k)
5024 {
5025   return usymtab_lookupQuietAux (s, k, FALSE);
5026 }
5027
5028 static /*@exposed@*/ /*@dependent@*/ uentry 
5029 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
5030 {
5031   return usymtab_lookupQuietAux (s, k, TRUE);
5032 }
5033
5034 /*@dependent@*/ /*@observer@*/ uentry
5035   usymtab_lookupSafe (cstring k)
5036   /*@globals utab@*/
5037 {
5038   DPRINTF (("Lookup safe: %s", k));
5039   return (usymtab_lookupAux (utab, k));
5040 }
5041
5042 uentry
5043   usymtab_lookupExpose (cstring k)
5044   /*@globals utab@*/
5045 {
5046   uentry ce = usymtab_lookupAux (utab, k);
5047
5048   if (uentry_isUndefined (ce))
5049     {
5050       llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5051     }
5052
5053   if (uentry_isPriv (ce))
5054     {
5055       llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5056     }
5057
5058   return ce;
5059 }
5060
5061 uentry usymtab_lookupExposeGlob (cstring k)
5062 {
5063   return (usymtab_lookupGlobSafe (k));
5064 }
5065
5066 uentry usymtab_lookupGlob (cstring k)
5067   /*@globals globtab@*/
5068 {
5069   uentry ce = usymtab_lookupAux (globtab, k);
5070
5071   if (uentry_isUndefined (ce))
5072     llfatalbug (message ("usymtab_lookup: not found: %s", k));
5073
5074   if (uentry_isPriv (ce))
5075     llfatalbug (message ("usymtab_lookup: private: %s", k));
5076
5077   DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5078   return ce;
5079 }
5080
5081 /*@observer@*/ uentry
5082   usymtab_lookupGlobSafe (cstring k)
5083   /*@globals globtab@*/
5084 {
5085   uentry ce = usymtab_lookupAux (globtab, k);
5086   DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5087   return ce;
5088 }
5089
5090 uentry usymtab_lookupEither (cstring k)
5091    /*@globals utab@*/
5092 {
5093   uentry ce = usymtab_lookupSafe (k);
5094
5095   if (uentry_isUndefined (ce))
5096     llfatalerror (message ("usymtab_lookup: not found: %s", k));
5097
5098   DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5099   return ce;
5100 }
5101
5102 ctype
5103 usymtab_lookupType (cstring k)
5104    /*@globals globtab@*/
5105 {
5106   typeId uid = usymtab_getTypeId (k);
5107
5108   if (typeId_isInvalid (uid))
5109     {
5110       llcontbug (message ("usymtab_lookupType: not found: %s", k));
5111       return ctype_unknown;
5112     }
5113   
5114   return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5115 }
5116
5117 ctype
5118 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5119 {
5120   typeId uid = usymtab_getTypeId (k);
5121
5122   if (typeId_isInvalid (uid))
5123     {
5124       llcontbug (message ("usymtab_lookupType: not found: %s", k));
5125       return ctype_unknown; 
5126     }
5127   
5128   return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5129 }
5130   
5131 /*
5132 ** if there is an unnamed lcl-specified struct tag matching
5133 ** the uentryList, return its datatype.  Otherwise, returns
5134 ** ctype_undefined.
5135 */
5136
5137 ctype
5138 usymtab_structFieldsType (uentryList f)
5139    /*@globals globtab@*/
5140 {
5141   return (usymtab_suFieldsType (f, TRUE));
5142 }
5143
5144 ctype
5145 usymtab_unionFieldsType (uentryList f)
5146    /*@globals globtab@*/
5147 {
5148   return (usymtab_suFieldsType (f, FALSE));
5149 }
5150
5151 static ctype
5152 usymtab_suFieldsType (uentryList f, bool isStruct)
5153   /*@globals globtab@*/
5154 {
5155   int i;
5156
5157   DPRINTF (("Fields: %s", uentryList_unparse (f)));
5158
5159   if (fileloc_isSpec (g_currentloc)) 
5160     {
5161       return (ctype_undefined);
5162     }
5163
5164   for (i = 0; i < globtab->nentries; i++)
5165     {
5166       uentry current = globtab->entries[i];
5167
5168       if ((isStruct 
5169            ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5170         {
5171           if (isFakeTag (uentry_rawName (current)))
5172             {
5173               ctype ct = uentry_getType (current);
5174               
5175               DPRINTF (("Check: %s", ctype_unparse (ct)));
5176
5177               if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5178                   && 
5179                   (uentry_isSpecified (current)
5180                    && uentryList_equivFields (f, ctype_getFields (ct))))
5181                 {
5182                   return uentry_getAbstractType (current);
5183                 }
5184               else
5185                 {
5186                   ;
5187                 }
5188             }
5189         }
5190     }
5191   
5192     return ctype_undefined;
5193 }
5194
5195 ctype
5196   usymtab_enumEnumNameListType (enumNameList f)
5197   /*@globals globtab@*/
5198 {
5199   int i;
5200
5201   for (i = 0; i < globtab->nentries; i++)
5202     {
5203       uentry current = globtab->entries[i];
5204
5205       if (uentry_isEnumTag (current))
5206         {
5207           if (isFakeTag (uentry_rawName (current)))
5208             {
5209               ctype ct = uentry_getType (current);
5210
5211               if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5212                 {
5213                   return uentry_getType (current);
5214                 }
5215             }
5216         }
5217     }
5218   
5219   return ctype_undefined;
5220 }
5221
5222 bool
5223 usymtab_exists (cstring k)
5224    /*@globals utab@*/
5225 {
5226   uentry ce = usymtab_lookupSafe (k);
5227   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5228 }
5229
5230 bool
5231 usymtab_existsReal (cstring k)
5232    /*@globals utab@*/
5233 {
5234   uentry ce = usymtab_lookupSafe (k);
5235
5236   return (!(uentry_isUndefined (ce)) 
5237           && !(uentry_isPriv (ce))
5238           && !(uentry_isExpandedMacro (ce)));
5239 }
5240
5241 bool
5242   usymtab_existsGlob (cstring k)
5243   /*@globals globtab@*/
5244 {
5245   uentry ce = usymtab_lookupAux (globtab, k);
5246
5247   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5248 }
5249
5250 bool
5251 usymtab_existsEither (cstring k)
5252   /*@globals utab@*/
5253 {
5254   uentry ce = usymtab_lookupAux (utab, k);
5255   
5256   return (uentry_isValid (ce));
5257 }
5258
5259 bool
5260   usymtab_existsGlobEither (cstring k)
5261   /*@globals globtab@*/
5262 {
5263   uentry ce = usymtab_lookupAux (globtab, k);
5264   
5265   return (uentry_isValid (ce));
5266 }
5267
5268 bool
5269 usymtab_existsType (cstring k)
5270   /*@globals globtab@*/
5271 {
5272   uentry ce = usymtab_lookupAux (globtab, k);
5273
5274   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5275 }
5276
5277 bool
5278 usymtab_existsTypeEither (cstring k)
5279   /*@globals globtab@*/
5280 {
5281   uentry ce;
5282   ce = usymtab_lookupAux (globtab, k);
5283   return (uentry_isValid (ce) && uentry_isDatatype (ce));
5284 }
5285
5286 bool
5287 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5288 {
5289   cstring sname = makeStruct (k);
5290   uentry ce = usymtab_lookupAux (globtab, sname);
5291   cstring_free (sname);  
5292   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5293 }
5294
5295 bool
5296 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5297 {
5298   cstring uname = makeUnion (k);
5299   uentry ce = usymtab_lookupAux (globtab, uname);
5300
5301   cstring_free (uname);
5302
5303   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5304 }
5305
5306 bool
5307 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5308 {
5309   cstring ename = makeEnum (k);
5310   uentry ce = usymtab_lookupAux (globtab, ename);
5311
5312   cstring_free (ename);
5313   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5314 }
5315
5316 bool usymtab_existsVar (cstring k)
5317    /*@globals utab@*/
5318 {
5319   uentry ce = usymtab_lookupSafe (k);
5320
5321   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5322 }
5323
5324 /*
5325 ** destructors
5326 */
5327
5328 static void
5329 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5330 {
5331   if (x != NULL)
5332     {
5333       int i;
5334
5335       for (i = 0; i < nentries; i++)
5336         {
5337           sfree (x[i]);
5338         }
5339       
5340       sfree (x);
5341     }
5342 }
5343   
5344 static void
5345 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5346   /*@globals globtab, utab, filetab@*/
5347 {
5348   int i;
5349
5350   DPRINTF (("Free level [%p]", u));
5351   aliasTable_free (u->aliases);
5352
5353   refTable_free (u->reftable, u->nentries);
5354
5355   if (u == filetab || u == globtab)
5356     {
5357       for (i = 0; i < u->nentries; i++)
5358         {
5359           DPRINTF (("Free complete: %d", i));
5360           DPRINTF (("Uentry: %s", uentry_unparse (u->entries[i])));
5361           uentry_freeComplete (u->entries[i]);
5362           u->entries[i] = uentry_undefined;
5363         }
5364     }
5365   else
5366     {
5367       for (i = 0; i < u->nentries; i++)
5368         {
5369           uentry_free (u->entries[i]);
5370           u->entries[i] = uentry_undefined;
5371         }
5372     }
5373
5374   guardSet_free (u->guards);
5375   sfree (u->entries);
5376
5377   if (u != globtab 
5378       && u != utab
5379       && u != filetab)
5380     {
5381       llassert (!cstringTable_isDefined (u->htable));
5382     }
5383
5384   sfree (u); /* evans 2002-07-12: was inside if */
5385 }
5386
5387 static void
5388 usymtab_freeAux (/*@only@*/ usymtab u)
5389    /*@globals globtab, utab, filetab@*/
5390    /*@modifies u@*/
5391 {
5392   while (u != GLOBAL_ENV)
5393     {
5394       usymtab t = u->env;
5395       usymtab_freeLevel (u);
5396       u = t;
5397       /*@-branchstate@*/ 
5398     } 
5399   /*@=branchstate@*/
5400 }
5401
5402 void usymtab_free () 
5403   /*@globals killed utab, globtab, filetab@*/ 
5404   /*@modifies utab@*/
5405 {
5406   dbgfree = TRUE;
5407   usymtab_freeAux (utab);
5408   utab = usymtab_undefined;
5409   /*@-globstate@*/
5410 } /*@=globstate@*/ /* Splint cannot tell that utab is killed */
5411
5412 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5413 {
5414   return (utab->lexlevel);
5415 }
5416
5417 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5418 {
5419   return (utab == globtab);
5420 }
5421
5422 bool usymtab_inFileScope () /*@globals utab@*/
5423 {
5424   return (utab->lexlevel == fileScope);
5425 }
5426
5427 bool usymtab_inFunctionScope () /*@globals utab@*/
5428 {
5429   return (utab->lexlevel == functionScope);
5430 }
5431
5432 void
5433 usymtab_replaceEntry (uentry s)
5434   /*@globals utab, globtab@*/
5435   /*@modifies utab, s@*/
5436 {
5437   usymtab_replaceEntryAux (utab, s);
5438 }
5439
5440 bool
5441 usymtab_matchForwardStruct (typeId u1, typeId u2)
5442    /*@globals globtab@*/
5443 {
5444   uentry ue1 = usymtab_getTypeEntry (u1);
5445   uentry ue2 = usymtab_getTypeEntry (u2);
5446
5447   if (uentry_isAnyTag (ue2))
5448     {
5449       ctype reptype = uentry_getType (ue1);
5450       
5451       if (ctype_isPointer (reptype))
5452         {
5453           ctype repbase = ctype_getBaseType (reptype);
5454   
5455           if (ctype_isUA (repbase))
5456             {
5457               typeId rtuid = ctype_typeId (repbase);
5458
5459               if (u2 == rtuid) return TRUE;
5460               
5461               if (typeId_isValid (rtuid))
5462                 {
5463                   reptype = uentry_getType (usymtab_getTypeEntry (rtuid));                
5464                   return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5465                 }
5466             }
5467         }
5468     }
5469   
5470   return FALSE;
5471 }
5472
5473 void usymtab_addGuards (guardSet guards)
5474   /*@modifies utab@*/
5475 {
5476   utab->guards = guardSet_union (utab->guards, guards);
5477   }
5478
5479 static bool usymtab_isGuardedAux (sRef s)
5480   /*@globals utab@*/
5481 {
5482   usymtab tab = utab;
5483   sRef base = sRef_getRootBase (s);
5484   int lowlevel = paramsScope;
5485   int baselevel = sRef_lexLevel (base);
5486
5487   if (sRef_isCvar (base))
5488     {
5489       lowlevel = baselevel;
5490       if (lowlevel < paramsScope) lowlevel = paramsScope;
5491     }
5492   
5493   while (tab->lexlevel >= lowlevel)
5494     {
5495       DPRINTF (("Is guarded? [%s] %s", 
5496                 guardSet_unparse (tab->guards),
5497                 sRef_unparseFull (s)));
5498
5499       if (guardSet_isGuarded (tab->guards, s))
5500         {
5501           /*
5502           if (!sRef_definitelyNull (s))
5503             {
5504               sRef_setNotNull (s, fileloc_undefined);
5505             }
5506             */
5507           return TRUE;
5508         }
5509
5510       tab = usymtab_dropEnv (tab);
5511     }
5512   
5513   return FALSE;
5514 }
5515
5516 void usymtab_unguard (sRef s) /*@modifies 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       if (guardSet_isGuarded (tab->guards, s))
5532         {
5533           guardSet_delete (tab->guards, s);
5534         }
5535       
5536       tab = usymtab_dropEnv (tab);
5537     }
5538 }
5539
5540 bool usymtab_isGuarded (sRef s)
5541 {
5542   DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5543   return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5544 }
5545
5546 bool usymtab_isDefinitelyNull (sRef s)
5547 {
5548   return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5549 }
5550
5551 bool usymtab_isDefinitelyNullDeep (sRef s)
5552 {
5553   return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5554 }
5555
5556 static bool usymtab_isDefinitelyNullAux (sRef s)
5557   /*@globals utab@*/
5558 {
5559   usymtab tab = utab;
5560   sRef base = sRef_getRootBase (s);
5561   int  lowlevel = paramsScope;
5562   
5563   if (sRef_isCvar (base))
5564     {
5565       lowlevel = sRef_lexLevel (base);
5566       if (lowlevel < paramsScope) lowlevel = paramsScope;
5567     }
5568   
5569   while (tab->lexlevel >= lowlevel)
5570     {
5571       if (guardSet_mustBeNull (tab->guards, s))
5572         {
5573           return TRUE;
5574         }
5575       
5576       while (tab->kind == US_CBRANCH) 
5577         {
5578           tab = tab->env;
5579         }
5580
5581       llassert (usymtab_isDefined (tab));
5582
5583       if (tab->kind == US_FBRANCH)
5584         {
5585           tab = tab->env;
5586           llassert (tab->kind == US_TBRANCH);
5587         }
5588       
5589       tab = tab->env;
5590     }
5591
5592   return FALSE;
5593 }
5594
5595 void
5596 usymtab_printGuards ()
5597   /*@globals utab, globtab@*/
5598 {
5599   usymtab ttab = utab;
5600
5601   while (ttab != globtab)
5602     {
5603       llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5604                       guardSet_unparse (ttab->guards)));
5605       ttab = ttab->env;
5606     }
5607 }
5608
5609 void
5610 usymtab_displayAllUses ()
5611   /*@globals utab, globtab@*/
5612 {
5613   usymtab copy;
5614
5615   /* only in top scope */
5616   llassert (utab == globtab);
5617
5618   /* need a copy, so order is not messed up by sort! */  
5619   copy = usymtab_shallowCopy (globtab); 
5620   
5621   qsort (copy->entries, (size_t)copy->nentries, 
5622          sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5623
5624   usymtab_entries (copy, ue)
5625     {
5626       if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5627         {
5628           filelocList uses = uentry_getUses (ue);
5629           int size = filelocList_realSize (uses);
5630
5631           if (fileloc_isDefined (uentry_whereDefined (ue)) 
5632               && !fileloc_isLib (uentry_whereDefined (ue))
5633               && (size > 0))
5634             {
5635               llmsg (message ("%q (%q), %d use%&:\n   %q", 
5636                               uentry_getName (ue),
5637                               fileloc_unparse (uentry_whereDefined (ue)),
5638                               size, filelocList_unparseUses (uses)));
5639             }
5640         }
5641     } end_usymtab_entries;
5642   
5643   usymtab_shallowFree (copy);
5644 }
5645
5646 static /*@dependent@*/ /*@exposed@*/ usymtab
5647 usymtab_getFileTab ()
5648   /*@globals filetab@*/
5649 {
5650   llassert (filetab != NULL);
5651
5652   return filetab;
5653 }
5654
5655 /*@only@*/ cstring
5656 usymtab_unparseStack ()
5657   /*@globals utab@*/
5658 {
5659   return (usymtab_unparseStackTab (utab));
5660 }
5661  
5662 static /*@only@*/ cstring
5663 usymtab_unparseStackTab (usymtab t)
5664 {
5665   bool firstOne = TRUE;
5666   cstring ret = cstring_makeLiteral ("[");
5667
5668   while (t != GLOBAL_ENV)
5669     {
5670       if (firstOne)
5671         {
5672           ret = message ("%q %q", ret, usymtab_typeName (t));
5673           firstOne = FALSE;
5674         }
5675       else
5676         {
5677           ret = message ("%q, %q", ret, usymtab_typeName (t));
5678         }
5679       t = t->env;
5680     }
5681
5682   ret = message ("%q ]", ret);
5683   return ret;
5684 }
5685
5686 static /*@only@*/ cstring
5687 usymtab_typeName (/*@notnull@*/ usymtab t)
5688 {
5689   switch (t->kind)
5690     {
5691     case US_GLOBAL:  return cstring_makeLiteral ("global");
5692     case US_NORMAL:  return cstring_makeLiteral ("normal");
5693     case US_TBRANCH: return cstring_makeLiteral ("true");
5694     case US_FBRANCH: return cstring_makeLiteral ("false");
5695     case US_CBRANCH: return cstring_makeLiteral ("case");
5696     case US_SWITCH:  return cstring_makeLiteral ("switch");
5697     }
5698   
5699   BADEXIT;
5700 }
5701
5702 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5703   /*@modifies utab@*/
5704 {
5705   if (!sRef_similar (s, al))
5706     {
5707       usymtab_addForceMustAlias (s, al);
5708     }
5709 }
5710
5711 /*
5712 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5713 */
5714
5715 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5716   /*@modifies utab@*/
5717 {
5718   /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5719   if (sRef_isMeaningful (s) 
5720       && sRef_isMeaningful (al)
5721       && !(sRef_isConst (s) || sRef_isConst (al))
5722       && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5723     {
5724       utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al); 
5725       DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5726
5727       /*
5728       ** for local variable, aliasing is symmetric 
5729       */
5730       
5731       if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5732         {
5733           utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s); 
5734         }
5735     }
5736   else
5737     {
5738       DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5739       DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5740     }
5741 }
5742
5743 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5744   /*@modifies utab@*/
5745 {
5746   utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al); 
5747 }
5748
5749 void usymtab_clearAlias (sRef s)
5750   /*@modifies utab, s@*/
5751 {
5752   
5753   aliasTable_clearAliases (utab->aliases, s); 
5754 }
5755
5756 sRefSet usymtab_allAliases (sRef s)
5757    /*@globals utab@*/  
5758 {
5759   if (sRef_isSomewhatMeaningful (s))
5760     {
5761       sRefSet ret;
5762             
5763       ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5764                                aliasTable_canAlias (utab->aliases, s));
5765       return (ret);
5766     }
5767   else
5768     {
5769       DPRINTF (("NOT A MEANINGFUL SREF!"));
5770       return sRefSet_undefined;
5771     }
5772 }
5773
5774 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5775      /*@globals utab@*/
5776 {
5777   if (sRef_isSomewhatMeaningful (s))
5778     {
5779       sRefSet res = aliasTable_canAlias (utab->aliases, s);
5780       return res;
5781     }
5782   
5783   return sRefSet_undefined;
5784 }
5785
5786 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5787      /*@globals utab@*/
5788 {
5789   return (aliasTable_aliasedBy (utab->aliases, s));
5790 }
5791
5792 /*@only@*/ cstring usymtab_unparseAliases ()
5793   /*@globals utab@*/
5794 {
5795   return (aliasTable_unparse (utab->aliases));
5796 }
5797
5798 /*
5799 ** Debugging routines:
5800 **    okay to leak storage here, only for debugging 
5801 */
5802
5803 /*@-mustfree@*/ 
5804
5805 void
5806 usymtab_printOut (void)
5807   /*@globals utab@*/
5808 {
5809   int i;
5810   usymtab s = utab;
5811   int depth = 0;
5812   char *ind = mstring_copy ("               ");
5813
5814   fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5815   
5816   while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5817     {
5818       cstring tname = usymtab_typeName (s);
5819
5820       if (depth < 5)
5821         {
5822           ind[depth * 3 + 1] = '\0';
5823         }
5824      
5825       fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5826                cstring_toCharsSafe (tname));
5827
5828       cstring_free (tname);
5829
5830       for (i = 0; i < s->nentries; i++)
5831         {
5832           cstring us = uentry_unparseFull (s->entries[i]);
5833           fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5834           cstring_free (us);
5835         }
5836       
5837       if (s->reftable != NULL && s->nentries > 0)
5838         {
5839           fprintf (g_warningstream, "\t<< Ref table >>\n");
5840
5841           for (i = 0; i < s->nentries; i++)
5842             {
5843               fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i, 
5844                        s->reftable[i]->level,
5845                        s->reftable[i]->index);
5846             }
5847         }
5848
5849       ind[depth * 3 + 1] = ' ';
5850       depth++;
5851       s = s->env;
5852     }
5853   fprintf (g_warningstream, "<<< end usymtab >>>\n");
5854   mstring_free (ind);
5855   return;
5856 }
5857
5858 void
5859 usymtab_printTypes ()
5860   /*@globals globtab@*/
5861 {
5862   usymtab_printAllAux (globtab);
5863 }
5864
5865 void 
5866 usymtab_printAll (void)
5867   /*@globals utab@*/
5868 {
5869   usymtab_printAllAux (utab);
5870 }
5871
5872 static void
5873 usymtab_printAllAux (usymtab s)
5874    /*@modifies g_warningstream@*/
5875 {
5876   int i;
5877   int depth = 0;
5878   char *ind = mstring_copy ("               ");
5879
5880   printf ("[[[ usymtab ]]]");
5881
5882   while (s != GLOBAL_ENV)
5883     {
5884       if (depth < 5)
5885         ind[depth * 3 + 1] = '\0';
5886       
5887       if (s->env == GLOBAL_ENV)
5888         {
5889           int looplow;
5890
5891           printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5892                   cstring_toCharsSafe (bool_unparse (s->mustBreak)), 
5893                   cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5894
5895           looplow = 0;
5896
5897           for (i = looplow; i < s->nentries; i++)
5898             {
5899               printf ("%s%3d. %s\n", ind, i, 
5900                       cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5901             }
5902         }
5903       else
5904         {
5905           printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5906                   cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5907                   cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5908
5909           for (i = 0; i < s->nentries; i++)
5910             {
5911               printf ("%s%3d %s\n", ind, i, 
5912                      cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5913             }
5914         }
5915       
5916       ind[depth * 3 + 1] = ' ';
5917       depth++;
5918       s = s->env;
5919     }
5920   printf ("----------\n");
5921 }
5922
5923 void
5924 usymtab_printComplete ()
5925   /*@globals utab@*/
5926 {
5927   int i;
5928   int depth = 0;
5929   char *ind = mstring_copy ("               ");
5930   usymtab s = utab;
5931
5932   while (s != GLOBAL_ENV)
5933     {
5934       if (depth < 5)
5935         {
5936           ind[depth * 3 + 1] = '\0';
5937         }
5938       
5939       if (s->env == GLOBAL_ENV)
5940         {
5941           int looplow;
5942
5943           printf ("level: %d\n", s->lexlevel);
5944
5945           looplow = 0;
5946
5947           for (i = looplow; i < s->nentries; i++)
5948             {
5949               printf ("%s%3d %s\n", ind, i, 
5950                       cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5951             }
5952         }
5953       else
5954         {
5955           printf ("level: %d\n", s->lexlevel);
5956           for (i = 0; i < s->nentries; i++)
5957             {
5958               printf ("%s%3d %s\n", ind, i, 
5959                      cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5960             }
5961         }
5962       
5963       ind[depth * 3 + 1] = ' ';
5964       depth++;
5965       s = s->env;
5966     }
5967
5968   printf ("----------\n");
5969   mstring_free (ind);
5970 }
5971
5972 # ifdef S_SPLINT_S
5973 static /*@only@*/ cstring /*@unused@*/ 
5974 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5975 {
5976   cstring c = message ("lexlevel: %d\n", s->lexlevel);
5977   int i;
5978
5979   for (i = 0; i < s->nentries; i++)
5980     {
5981       c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5982     }
5983
5984   c = message ("%q\n=========", c);
5985   return (c);
5986 }
5987
5988 static cstring /*@unused@*/ /*@only@*/ 
5989 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5990 {
5991   cstring c = message ("[%d/%s/%s] ", s->lexlevel, 
5992                        bool_unparse (s->mustBreak), 
5993                        exitkind_unparse (s->exitCode));
5994   int i;
5995
5996   for (i = 0; i < s->nentries; i++)
5997     {
5998       sRef sr = uentry_getSref (s->entries[i]);
5999
6000       if (i == 0)
6001         {
6002           c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]), 
6003                        sRef_isStateDefined (sr));
6004         }
6005       else
6006         {
6007           c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]), 
6008                        sRef_isStateDefined (sr));
6009         }
6010
6011     }
6012
6013   return (c);
6014 }
6015 # endif
6016
6017 void
6018 usymtab_printLocal (void)
6019   /*@globals utab@*/
6020 {
6021   int i;
6022   usymtab s = utab;
6023
6024   printf ("lexlevel: %d\n", s->lexlevel);
6025
6026   for (i = 0; i < s->nentries; i++)
6027     {
6028       printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6029     }
6030   
6031   while (s->lexlevel > 1)
6032     {
6033       s = s->env;
6034     }
6035
6036   llassert (usymtab_isDefined (s));
6037
6038   printf ("Params:\n");
6039
6040   for (i = 0; i < s->nentries; i++)
6041     {
6042       printf ("%d: %s\n", i, 
6043               cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6044     }
6045 }
6046 /*@=mustfree@*/
6047
6048 static bool checkDistinctExternalName (uentry e)
6049   /*@globals globtab@*/
6050   /*@modifies *g_warningstream@*/
6051 {
6052   size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6053   bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6054   bool gotone = FALSE;
6055   bool extras = FALSE;
6056   bool hasError = FALSE;
6057   cstring name = uentry_rawName (e);
6058   usymtab st = globtab;
6059
6060   if (checklen == 0)
6061     {
6062       ;
6063     }
6064   else
6065     {
6066       if (uentry_isAnyTag (e)) 
6067         {
6068           checklen++;  /* the tag marker doesn't count */
6069         }
6070     }
6071
6072   usymtab_entries (st, oe)
6073     {
6074       if (uentry_sameObject (oe, e))
6075         {
6076           continue;
6077         }
6078
6079       if (checklen == 0)
6080         {
6081           if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6082             {
6083               if (gotone)
6084                 {
6085                   extras = TRUE;
6086                   break;
6087                 }
6088               
6089               if (optgenerror 
6090                   (FLG_DISTINCTEXTERNALNAMES,
6091                    message 
6092                    ("External identifier %q is not distinguishable from %q "
6093                     "because alphabetical case is ignored",
6094                     uentry_getName (e),
6095                     uentry_getName (oe)),
6096                    uentry_whereLast (e)))
6097                 {
6098                   uentry_showWhereAny (oe);
6099                   uentry_setHasNameError (oe);
6100                   gotone = TRUE;
6101                 }
6102             }
6103         }
6104       else
6105         {
6106           if (ignorecase)
6107             {
6108               if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6109                                                    name, checklen))
6110                 {
6111                   if (gotone)
6112                     {
6113                       extras = TRUE;
6114                       break;
6115                     }
6116                   
6117                   if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6118                     {
6119                       if (optgenerror 
6120                           (FLG_DISTINCTEXTERNALNAMES,
6121                            /*@-sefparams@*/
6122                            message 
6123                            ("External identifier %q is not distinguishable from %q "
6124                             "in the first %d characters (%q)",
6125                             uentry_getName (e),
6126                             uentry_getName (oe),
6127                             size_toInt (checklen),
6128                             cstring_clip (uentry_getName (e), checklen)),
6129                            /*@=sefparams@*/
6130                            uentry_whereLast (e)))
6131                         {
6132                           uentry_showWhereAny (oe);
6133                           uentry_setHasNameError (oe);
6134                           gotone = TRUE;
6135                         }
6136                     }
6137                   else
6138                     {
6139                       if (gotone)
6140                         {
6141                           extras = TRUE;
6142                           break;
6143                         }
6144                       
6145                       if (optgenerror 
6146                           (FLG_DISTINCTEXTERNALNAMES,
6147                            message 
6148                            ("External identifier %q is not distinguishable from %q "
6149                             "in the first %d characters because alphabetical case "
6150                             "is ignored",
6151                             uentry_getName (e),
6152                             uentry_getName (oe),
6153                             size_toInt (checklen)),
6154                            uentry_whereLast (e)))
6155                         {
6156                           uentry_showWhereAny (oe);
6157                           uentry_setHasNameError (oe);
6158                           gotone = TRUE;
6159                         }
6160                     }
6161                 }
6162             }
6163           else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6164             {
6165               if (gotone)
6166                 {
6167                   extras = TRUE;
6168                   break;
6169                 }
6170               
6171               if (optgenerror 
6172                   (FLG_DISTINCTEXTERNALNAMES,
6173                    /*@-sefparams@*/
6174                    message 
6175                    ("External identifier %q is not distinguishable from %q "
6176                     "in the first %d characters (%q)",
6177                     uentry_getName (e),
6178                     uentry_getName (oe),
6179                     size_toInt (checklen),
6180                     cstring_clip (uentry_getName (e), checklen)),
6181                    /*@=sefparams@*/
6182                    uentry_whereLast (e)))
6183                 {
6184                   uentry_showWhereAny (oe);
6185                   uentry_setHasNameError (oe);
6186                   gotone = TRUE;
6187                 }
6188             }
6189           else
6190             {
6191               ; /* okay */
6192             }
6193         }
6194     } end_usymtab_entries ;
6195
6196   hasError = gotone;
6197   
6198   if (extras)
6199     {
6200       llgenindentmsgnoloc
6201         (cstring_makeLiteral ("One or more additional "
6202                               "indistinguishable external "
6203                               "names not reported"));
6204     }
6205
6206   return hasError;
6207 }
6208
6209 static bool checkDistinctInternalName (uentry e)
6210   /*@globals utab@*/
6211   /*@modifies *g_warningstream@*/
6212 {
6213   usymtab ttab = utab;
6214   cstring name = uentry_rawName (e);
6215   size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6216   bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6217   bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6218
6219   if (uentry_isAnyTag (e) && (numchars != 0))
6220     {
6221       numchars++;  /* the tag marker doesn't count */
6222     }
6223   
6224   while (usymtab_isDefined (ttab))
6225     {
6226       usymtab_entries (ttab, oe)
6227         {
6228           if (uentry_sameObject (oe, e))
6229             {
6230               /*@innercontinue@*/ continue;
6231             }
6232
6233           switch (cstring_genericEqual
6234                   (name, uentry_rawName (oe),
6235                    numchars, caseinsensitive, lookalike))
6236             {
6237             case CGE_DISTINCT: /* okay */
6238               /*@switchbreak@*/ 
6239               break;
6240             case CGE_SAME:
6241               if (cstring_equal (name, uentry_rawName (oe)))
6242                 {
6243                   ; /* got a shadow error */
6244                 }
6245               else
6246                 {
6247                   if (optgenerror 
6248                       (FLG_DISTINCTINTERNALNAMES,
6249                        /*@-sefparams@*/
6250                        message 
6251                        ("Internal identifier %q is not distinguishable from %q "
6252                         "in the first %d characters (%q)",
6253                         uentry_getName (e),
6254                         uentry_getName (oe),
6255                         size_toInt (numchars),
6256                         cstring_clip (uentry_getName (e), numchars)),
6257                        /*@=sefparams@*/
6258                        uentry_whereLast (e)))
6259                     {
6260                       uentry_showWhereAny (oe);
6261                       uentry_setHasNameError (oe);
6262                       return TRUE;
6263                     }
6264                 }
6265               /*@switchbreak@*/
6266               break;
6267             case CGE_CASE:
6268               if (numchars == 0 || (cstring_length (name) <= numchars))
6269                 {
6270                   if (optgenerror 
6271                       (FLG_DISTINCTINTERNALNAMES,
6272                        message 
6273                        ("Internal identifier %q is not distinguishable from %q "
6274                         "without case sensitivity",
6275                         uentry_getName (e),
6276                         uentry_getName (oe)),
6277                        uentry_whereLast (e)))
6278                     {
6279                       uentry_showWhereAny (oe);
6280                       uentry_setHasNameError (oe);
6281                       return TRUE;
6282                     }
6283                 }
6284               else 
6285                 {
6286                   if (optgenerror 
6287                       (FLG_DISTINCTINTERNALNAMES,
6288                        message 
6289                        ("Internal identifier %q is not distinguishable from %q "
6290                         "in the first %d characters without case sensitivity",
6291                         uentry_getName (e),
6292                         uentry_getName (oe),
6293                         size_toInt (numchars)),
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_LOOKALIKE:
6304               if (numchars == 0 
6305                   || (cstring_length (name) <= numchars))
6306                 {
6307                   if (optgenerror 
6308                       (FLG_DISTINCTINTERNALNAMES,
6309                        message 
6310                        ("Internal identifier %q is not distinguishable from %q "
6311                         "except by lookalike characters",
6312                         uentry_getName (e),
6313                         uentry_getName (oe)),
6314                        uentry_whereLast (e)))
6315                     {
6316                       uentry_showWhereAny (oe);
6317                       uentry_setHasNameError (oe);
6318                       return TRUE;
6319                     }
6320                 }
6321               else 
6322                 {
6323                   if (optgenerror 
6324                       (FLG_DISTINCTINTERNALNAMES,
6325                        message 
6326                        ("Internal identifier %q is not distinguishable from %q "
6327                         "in the first %d characters except by lookalike characters",
6328                         uentry_getName (e),
6329                         uentry_getName (oe),
6330                         size_toInt (numchars)),
6331                        uentry_whereLast (e)))
6332                     {
6333                       uentry_showWhereAny (oe);
6334                       uentry_setHasNameError (oe);
6335                       return TRUE;
6336                     }
6337                 }
6338             }
6339         } end_usymtab_entries ;
6340       
6341       ttab = ttab->env;
6342     }
6343
6344   return FALSE;
6345 }
6346
6347 void usymtab_checkDistinctName (uentry e, int scope)
6348    /*@globals utab, globtab@*/
6349 {
6350   bool hasError = FALSE;
6351   fileloc where = uentry_whereLast (e);
6352
6353   if (!fileloc_isPreproc (where)  && !fileloc_isBuiltin (where))
6354     {
6355       if (scope == globScope)
6356         {
6357           if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6358             {
6359               hasError = checkDistinctExternalName (e);
6360             }
6361         }
6362       
6363       if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6364         {
6365           hasError = checkDistinctInternalName (e);
6366         }
6367     }
6368
6369   if (hasError)
6370     {
6371       uentry_setHasNameError (e);
6372     }
6373 }
6374
6375 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6376 {
6377   uentry ue;
6378
6379   ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6380   llassert (uentry_isValid (ue));
6381
6382   return uentry_getSref (ue);
6383 }
6384
6385
6386 # ifdef DEBUGSPLINT
6387 /*
6388 ** For debugging only
6389 */
6390
6391 void
6392 usymtab_checkAllValid () /*@globals utab@*/ 
6393 {
6394   usymtab tab = utab;
6395
6396   while (tab != GLOBAL_ENV)
6397     {
6398       int i;
6399
6400       for (i = 0; i < utab->nentries; i++)
6401         {
6402           uentry e = utab->entries[i];
6403           
6404           uentry_checkValid (e);
6405         }
6406
6407       aliasTable_checkValid (tab->aliases);
6408       tab = tab->env;
6409     }
6410 }
6411 # endif
6412
6413
6414
6415
6416
6417
This page took 0.609393 seconds and 3 git commands to generate.