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