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