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