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