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