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