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