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