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