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