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