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