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