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