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