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