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