]> 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                           DPRINTF (("decl: %s", uentry_unparseFull (e)));
3189                         }
3190                     }
3191                 }
3192               else
3193                 {
3194                   fileloc sloc = uentry_whereSpecified (e);
3195
3196                   if (fileloc_isDefined (sloc) 
3197                       && !fileloc_isImport (sloc)
3198                       && !fileloc_isLib (sloc)
3199                       && !fileloc_isPreproc (sloc)
3200                       && !uentry_isFakeTag (e))
3201                     {
3202                       if (uentry_isVariable (e) || uentry_isFunction (e))
3203                         {
3204                           voptgenerror 
3205                             (FLG_SPECUNDEF,
3206                              message ("%s %q specified but not declared or defined",
3207                                       ekind_capName (uentry_getKind (e)),
3208                                       uentry_getName (e)),
3209                              sloc);
3210                         }
3211                       else
3212                         {
3213                           voptgenerror 
3214                             (FLG_SPECUNDEF,
3215                              message ("%s %q specified but not defined",
3216                                       ekind_capName (uentry_getKind (e)),
3217                                       uentry_getName (e)),
3218                              sloc);
3219                         }
3220                     }
3221                 }
3222             }
3223         }
3224     }
3225 }
3226
3227 void usymtab_exportHeader (void)
3228      /*@globals utab@*/
3229 {
3230   int i;
3231
3232   for (i = 0; i < utab->nentries; i++)
3233     {
3234       uentry ce = utab->entries[i];
3235
3236       if (!uentry_isDatatype (ce) 
3237           && !uentry_isAnyTag (ce) 
3238           && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3239           && !uentry_isExternal (ce)
3240           && !uentry_isForward (ce))
3241         {
3242           fileloc fwhere = uentry_whereDeclared (ce);
3243
3244           if (fileloc_isUndefined (fwhere)
3245               && uentry_isFunction (ce))
3246             {
3247               fwhere = uentry_whereDefined (ce);
3248             }
3249
3250           if (fileloc_isDefined (fwhere) 
3251               && !fileloc_isHeader (fwhere)
3252               && !fileloc_isXHFile (fwhere)
3253               && !(fileloc_isSpecialFile (fwhere)
3254                    && !context_getFlag (FLG_UNUSEDSPECIAL)))
3255             {
3256               if (uentry_isVariable (ce))
3257                 {
3258                   if (optgenerror
3259                       (FLG_EXPORTHEADERVAR,
3260                        message ("%s %q exported but not declared in header file", 
3261                                 ekind_capName (uentry_getKind (ce)),
3262                                 uentry_getName (ce)),
3263                        fwhere))
3264                     {
3265                       uentry_showDefSpecInfo (ce, fwhere);
3266                     }
3267                 }
3268               else
3269                 {
3270                   if (!uentry_isIter (ce)
3271                       && !uentry_isEndIter (ce)
3272                       && !uentry_isExpandedMacro (ce))
3273                     {
3274                       if (uentry_isFunction (ce) 
3275                           && cstring_equalLit (uentry_rawName (ce), "main"))
3276                         {
3277                           ; /* no error for main */
3278                         }
3279                       else
3280                         {
3281                           if (optgenerror
3282                               (FLG_EXPORTHEADER,
3283                                message ("%s %q exported but not declared "
3284                                         "in header file", 
3285                                         ekind_capName (uentry_getKind (ce)),
3286                                         uentry_getName (ce)),
3287                                fwhere))
3288                             {
3289                               uentry_showDefSpecInfo (ce, fwhere);
3290                             }
3291                         }
3292                     }
3293                 }
3294             }
3295         }
3296     }
3297 }
3298
3299 void usymtab_exportLocal (void)
3300    /*@globals utab@*/
3301 {
3302   int i;
3303   
3304   for (i = 0; i < utab->nentries; i++)
3305     {
3306       uentry ce = utab->entries[i];
3307       
3308       if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce) 
3309           && !uentry_isEitherConstant (ce) 
3310           && !uentry_isIter (ce)
3311           && !uentry_isEndIter (ce)
3312           && !uentry_isExpandedMacro (ce)
3313           && uentry_isUsed (ce))
3314         {
3315           /* check static uses */
3316           filelocList fuses = uentry_getUses (ce);
3317           fileloc mod = uentry_whereDefined (ce);
3318           bool ok = filelocList_isEmpty (fuses);
3319           fileloc fwhere = uentry_whereDeclared (ce);
3320
3321           if (fileloc_isSpecialFile (fwhere)
3322               && !context_getFlag (FLG_UNUSEDSPECIAL))
3323             {
3324               ok = TRUE; /* no errors for special files */
3325             }
3326           else
3327             {
3328               filelocList_elements (fuses, uloc)
3329                 {
3330                   if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3331                     {
3332                       ok = TRUE;
3333                       /*@innerbreak@*/ break;
3334                     }
3335                 } end_filelocList_elements;
3336             }
3337
3338           if (!ok)
3339             {
3340               if (optgenerror
3341                   (FLG_EXPORTLOCAL,
3342                    message ("%s exported but not used outside %s: %q", 
3343                             ekind_capName (uentry_getKind (ce)),
3344                             fileloc_getBase (mod),
3345                             uentry_getName (ce)),
3346                    fwhere))
3347                 {
3348                   uentry_showDefSpecInfo (ce, fwhere);
3349                 }
3350             }
3351         }
3352     }
3353 }
3354
3355 void
3356 usymtab_allUsed (void)
3357   /*@globals utab@*/
3358 {
3359   int i;
3360   bool isFileStatic = usymtab_inFileScope ();
3361   cstring last_file = cstring_undefined;
3362
3363   for (i = 0; i < utab->nentries; i++)
3364     {
3365       bool hasError = FALSE;
3366       uentry ce = utab->entries[i];
3367       fileloc fwhere = uentry_whereDeclared (ce);
3368
3369       if (fileloc_isUndefined (fwhere))
3370         {
3371           fwhere = uentry_whereDefined (ce);
3372         }
3373
3374       if (fileloc_isInvalid (fwhere) 
3375           || fileloc_isLib (fwhere) 
3376           || fileloc_isBuiltin (fwhere)
3377           || ((fileloc_isSpecialFile (fwhere)
3378                || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3379               && !context_getFlag (FLG_UNUSEDSPECIAL)))
3380         {
3381           ;
3382         }
3383       else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3384         {
3385           cstring fname = fileloc_filename (fwhere);
3386
3387           if (cstring_isUndefined (last_file))
3388             {
3389               last_file = fname;
3390             }
3391           else if (cstring_equal (fname, last_file))
3392             {
3393             }
3394           else
3395             {
3396               cleanupMessages ();
3397               last_file = fname;
3398             } 
3399           
3400           if (uentry_isParam (ce))
3401             {
3402               if (context_inMacro ())
3403                 {
3404                   sRef cref = uentry_getSref (ce);
3405
3406                   if (uentry_isYield (ce))
3407                     {
3408                       ; /* no checks (for now) */
3409                     }
3410                   else if (sRef_isSafe (cref))
3411                     {
3412                       ; /* no error */
3413                     }
3414                   else
3415                     {
3416                       if (uentry_hasRealName (ce))
3417                         {
3418                           hasError = 
3419                             optgenerror (FLG_MACROPARAMS,
3420                                          message ("Macro parameter %q not used", 
3421                                                   uentry_getName (ce)),
3422                                          fwhere);
3423                         }
3424                     }
3425                 }
3426               else 
3427                 {
3428                   if (cstring_equalFree (uentry_getName (ce), 
3429                                          cstring_makeLiteral ("...")))
3430                     {
3431                       ;
3432                     }
3433                   else
3434                     {
3435                       hasError = optgenerror (FLG_PARAMUNUSED,
3436                                               message ("Parameter %q not used",
3437                                                        uentry_getName (ce)),
3438                                               fwhere);
3439                     }
3440                 }
3441             } /* isParam */
3442           else if (uentry_isFunction (ce) || uentry_isIter (ce))
3443             {
3444               if (fileloc_isUser (fwhere))
3445                 {
3446                   hasError = optgenerror
3447                     (FLG_FUNCUNUSED, 
3448                      message ("%q %q declared but not used", 
3449                               cstring_makeLiteral 
3450                               (uentry_isIter (ce) ? "Iterator" 
3451                                : (isFileStatic ? "File static function" : "Function")),
3452                               uentry_getName (ce)),
3453                      fwhere);
3454                 }
3455             }
3456           else if (uentry_isEndIter (ce))
3457             {
3458               ; /* no error (already reported for iter */
3459             }
3460           else if (uentry_isEnumConstant (ce))
3461             {
3462               if (fileloc_isUser (fwhere))
3463                 {
3464                   hasError = optgenerror
3465                     (FLG_ENUMMEMUNUSED,
3466                      message ("Enum member %q not used", 
3467                               uentry_getName (ce)),
3468                      fwhere);
3469                 }
3470             }
3471           else if (uentry_isConstant (ce))
3472             {
3473               if (fileloc_isUser (fwhere))
3474                 {
3475                   hasError = optgenerror
3476                     (FLG_CONSTUNUSED,
3477                      message ("Constant %q declared but not used", 
3478                               uentry_getName (ce)),
3479                      fwhere);
3480                 }
3481             }
3482           else if (uentry_isDatatype (ce))
3483             {
3484               if (fileloc_isUser (fwhere))
3485                 {
3486                   hasError = optgenerror
3487                     (FLG_TYPEUNUSED,
3488                      message ("Type %q declared but not used", 
3489                               uentry_getName (ce)),
3490                      fwhere);
3491                 }
3492             }
3493           else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3494             { /* errors for ref params will be reported in the next scope */
3495               llassertprint (uentry_isVar (ce), 
3496                              ("ce: %s", uentry_unparseFull (ce)));
3497
3498               if (ctype_isFunction (uentry_getType (ce)))
3499                 {
3500                   if (fileloc_isUser (fwhere))
3501                     {
3502                       hasError = optgenerror
3503                         (FLG_FUNCUNUSED,
3504                          message ("%q %q declared but not used", 
3505                                   cstring_makeLiteral 
3506                                   (isFileStatic ? "File static function" 
3507                                    : "Function"),
3508                                   uentry_getName (ce)),
3509                          fwhere);
3510                     }
3511                 }
3512               else 
3513                 {
3514                   if (fileloc_isUser (fwhere))
3515                     {
3516                       
3517                       
3518                       hasError = optgenerror 
3519                         (FLG_VARUNUSED,
3520                          message ("%q %q declared but not used", 
3521                                   cstring_makeLiteral 
3522                                   (isFileStatic ? "File static variable" 
3523                                    : "Variable"), 
3524                                   uentry_getName (ce)),
3525                          fwhere);
3526                     }
3527                 }
3528             }
3529           else
3530             {
3531               ; /* no errors */
3532             }
3533         } /* unused */
3534       else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3535         { /* check all fields */
3536           ctype ct = uentry_getRealType (ce); 
3537
3538           
3539           while (ctype_isAP (ct))
3540             {
3541               ct = ctype_getBaseType (ct);
3542             }
3543
3544           if (ctype_isSU (ct))
3545             {
3546               uentryList fields = ctype_getFields (ct);
3547
3548               uentryList_elements (fields, field)
3549                 {
3550                   if (!uentry_isUsed (field))
3551                     {
3552                       if (uentry_hasName (ce))
3553                         {
3554                           hasError |= optgenerror 
3555                             (FLG_FIELDUNUSED,
3556                              message ("Field %q of %s %q declared but not used", 
3557                                       uentry_getName (field),
3558                                       cstring_makeLiteralTemp
3559                                       (ctype_isStruct (ct) ? "structure" : "union"),
3560                                       uentry_getName (ce)),
3561                              uentry_whereEarliest (field));
3562                         }
3563                       else
3564                         {
3565                           /*
3566                           ** evans 2001-06-08
3567                           ** Can't report these errors for unnamed structs.
3568                           ** No way to tell when there are multiple consistent
3569                           ** unnamed structure types.  (Could go through table
3570                           ** and mark them all unused...)
3571
3572                           hasError |= optgenerror 
3573                             (FLG_FIELDUNUSED,
3574                              message ("Field %q of unnamed %s declared but not used", 
3575                                       uentry_getName (field),
3576                                       cstring_makeLiteralTemp
3577                                       (ctype_isStruct (ct) ? "structure" : "union")),
3578                              uentry_whereEarliest (field));
3579
3580                           */
3581                         }
3582                       
3583                       uentry_setUsed (field, fileloc_undefined);
3584                     }
3585                 } end_uentryList_elements;
3586             }
3587         }
3588       else
3589         {
3590           ; /* no errors */
3591         }
3592
3593       if (hasError)
3594         {
3595           if (uentry_isParam (ce) && context_inMacro ())
3596             {
3597               if (fileloc_isDefined (uentry_whereSpecified (ce)))
3598                 {
3599                   uentry_showWhereSpecified (ce);
3600                 }
3601             }
3602           else
3603             {
3604               uentry_showDefSpecInfo (ce, fwhere);
3605             }
3606
3607           uentry_setUsed (ce, fileloc_undefined);
3608         }
3609     }
3610 }
3611
3612 static void
3613 checkGlobalReturn (uentry glob, sRef orig)
3614 {
3615   sRef sr = uentry_getSref (glob);
3616   
3617   DPRINTF (("Check global return: %s // orig: %s // sr: %s",
3618             uentry_unparseFull (glob),
3619             sRef_unparseFull (orig),
3620             sRef_unparseFull (sr)));
3621
3622   DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3623
3624   if (context_getFlag (FLG_GLOBSTATE))
3625     {
3626       DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3627       
3628       if (sRef_isKilledGlob (orig))
3629         {
3630           if (sRef_isStateUndefined (sr)
3631               || sRef_isUnuseable (sr)
3632               || sRef_isStateUnknown (sr)
3633               || sRef_isDead (sr))
3634             {
3635               ;
3636             }
3637           else
3638             {
3639               ctype ct = ctype_realType (uentry_getType (glob));
3640
3641               if (ctype_isVisiblySharable (ct))
3642                 {
3643                   if (optgenerror 
3644                       (FLG_GLOBSTATE,
3645                        message 
3646                        ("Killed global %q (type %s) not released before return",
3647                         uentry_getName (glob),
3648                         ctype_unparse (ct)),
3649                        g_currentloc))
3650                     {
3651                       sRef_showStateInfo (sr);
3652                     }
3653                 }
3654               else
3655                 {
3656                   sRef_protectDerivs ();
3657                   (void) checkGlobalDestroyed (sr, g_currentloc);
3658                   sRef_clearProtectDerivs ();
3659                 }
3660             }
3661         }
3662       else
3663         {
3664           if (sRef_isStateUndefined (sr))
3665             {
3666               if (optgenerror (FLG_GLOBSTATE,
3667                                message 
3668                                ("Function returns with global %q undefined",
3669                                 uentry_getName (glob)),
3670                                g_currentloc))
3671                 {
3672                   sRef_showStateInfo (sr);
3673                 }
3674             }
3675           else 
3676             {
3677               if (sRef_isDead (sr))
3678                 {
3679                   if (optgenerror 
3680                       (FLG_GLOBSTATE,
3681                        message ("Function returns with global %q "
3682                                 "referencing released storage",
3683                                 uentry_getName (glob)),
3684                        g_currentloc))
3685                     {
3686                       sRef_showStateInfo (sr);
3687                       sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3688                     }
3689                 }
3690               
3691               if (ctype_isRealPointer (uentry_getType (glob))
3692                   && sRef_possiblyNull (sr)
3693                   && !uentry_possiblyNull (glob))
3694                 {
3695                   if (optgenerror 
3696                       (FLG_GLOBSTATE,
3697                        message ("Function returns with non-null global %q "
3698                                 "referencing null storage",
3699                                 uentry_getName (glob)),
3700                        g_currentloc))
3701                     {
3702                       sRef_showNullInfo (sr);
3703                     }
3704                 }
3705               else
3706                 {
3707                   checkGlobReturn (glob);
3708                 }
3709             }
3710         }
3711     }
3712 }
3713
3714 /*
3715 ** remember: check alias globals
3716 */
3717
3718 void usymtab_checkFinalScope (bool isReturn)
3719   /*@globals utab@*/
3720 {
3721   bool mustFree = context_getFlag (FLG_MUSTFREE);
3722   bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3723   /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3724   sRefSet checked = sRefSet_new ();
3725   usymtab stab = utab;
3726   int i;
3727     
3728   /*
3729   ** need to check all scopes out to function parameters.
3730   */
3731
3732   do 
3733     {
3734       for (i = 0; i < stab->nentries; i++)
3735         {
3736           uentry ce = stab->entries[i];
3737           sRef sr = uentry_getSref (ce);
3738           sRef rb = sRef_getRootBase (sr);
3739           valueTable tvalues;
3740
3741           /*
3742           ** Shouldn't check if shadow checked in deeper scope:
3743           */
3744
3745           if (stab != utab)
3746             {
3747               uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3748
3749               if (!uentry_sameObject (ce, oue))
3750                 {
3751                   DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce),
3752                             uentry_unparseFull (oue)));
3753                   /*@i32  what if it is one an alternate branch? */
3754                   /*@innercontinue@*/ continue;
3755                 }
3756             }
3757                             
3758           DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3759           
3760           if (ctype_isFunction (uentry_getType (ce)))
3761             {
3762               /*@innercontinue@*/ continue;
3763             }
3764
3765           if (uentry_isAnyParam (ce)
3766               || uentry_isRefParam (ce)
3767               || sRef_isFileOrGlobalScope (rb))
3768             {
3769               /* Don't do the loseref check...but should check state! */
3770             }
3771           else if (sRef_isDefinitelyNull (sr)
3772                    || usymtab_isDefinitelyNull (sr))
3773             {
3774               /*
3775               ** No state reference errors for definitely null references.
3776               */
3777             }
3778           else
3779             {
3780               DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce), 
3781                         sRef_unparseFull (sr)));
3782               
3783               tvalues = sRef_getValueTable (sr);
3784               
3785               valueTable_elements (tvalues, fkey, fval) {
3786                 metaStateInfo minfo;
3787                 cstring msg = cstring_undefined;
3788                 int nval;
3789                 
3790                 minfo = context_lookupMetaStateInfo (fkey);
3791                 llassert (metaStateInfo_isDefined (minfo));
3792                 
3793                 if (stateValue_isError (fval))
3794                   {
3795                     ;
3796                   }
3797                 else 
3798                   {
3799                     DPRINTF (("Check: %s / %s / %s", fkey,
3800                               metaStateInfo_unparse (minfo),
3801                               stateValue_unparse (fval)));
3802                     
3803                     minfo = context_lookupMetaStateInfo (fkey);
3804                     
3805                     nval = stateCombinationTable_lookupLoseReference 
3806                       (metaStateInfo_getTransferTable (minfo), 
3807                        stateValue_getValue (fval), &msg);
3808                     
3809                     if (cstring_isDefined (msg)) 
3810                       {
3811                         /*@i32 print extra info for assignments@*/
3812                         DPRINTF (("From: %s", sRef_unparseFull (sr)));
3813                         DPRINTF (("Null? %s / %s",
3814                                   bool_unparse (sRef_isDefinitelyNull (sr)),
3815                                   bool_unparse (usymtab_isGuarded (sr))));
3816                         
3817                         if (optgenerror 
3818                             (FLG_STATETRANSFER,
3819                              message
3820                              ("%s loses reference %q in invalid state %q (%s)",
3821                               cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3822                               uentry_getName (ce),
3823                               stateValue_unparseValue (fval, minfo),
3824                               msg),
3825                              g_currentloc))
3826                           {
3827                             stateValue_show (fval, minfo);
3828                           }
3829                         else
3830                           {
3831                             DPRINTF (("Suppressed transfer error: %s", msg));
3832                           }
3833                       }
3834                   }
3835               } end_valueTable_elements;
3836             }
3837
3838           if (mustFree)
3839             {
3840               DPRINTF (("Check entry: %s", uentry_unparseFull (ce)));
3841               
3842               if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3843                 {
3844                   if (ctype_isRealSU (uentry_getType (ce))
3845                       && !uentry_isAnyParam (ce)
3846                       && !uentry_isRefParam (ce)
3847                       && !uentry_isStatic (ce)
3848                       && !sRef_isDependent (sr)
3849                       && !sRef_isOwned (sr))
3850                     {
3851                       sRefSet als = usymtab_allAliases (sr);
3852                       
3853                       if (sRefSet_isEmpty (als))
3854                         {
3855                           checkLocalDestroyed (sr, g_currentloc);
3856                         }
3857                       else
3858                         {
3859                           /* aliased, no problem */ ;
3860                         }
3861
3862                       sRefSet_free (als);
3863                     }
3864                   else if
3865                     (!uentry_isStatic (ce)
3866                      && ((sRef_isNewRef (sr))
3867                          || (((sRef_isOnly (sr) || sRef_isFresh (sr) 
3868                                || sRef_isKeep (sr) || sRef_isOwned (sr))
3869                               && !sRef_isDead (sr))
3870                              && (!sRef_definitelyNull (sr))
3871                              && (!usymtab_isDefinitelyNull (sr)))))
3872                       {
3873                         bool hasError = TRUE;
3874                         
3875                         DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3876
3877                         /*
3878                         ** If its a scope exit, check if there is an alias.
3879                         ** If so, make it only.  If not, there is an error.
3880                         */
3881                         
3882                         if (!isReturn)
3883                           {
3884                             if (canLoseReference (sr, g_currentloc))
3885                               {
3886                                 DPRINTF (("Can lose!"));
3887                                 hasError = FALSE;
3888                               }
3889                           }
3890                         
3891                         if (hasError)
3892                           {
3893                             if (sRef_hasLastReference (sr))
3894                               {
3895                                 sRef ar = sRef_getAliasInfoRef (sr);
3896                                 
3897                                 if (optgenerror 
3898                                     (FLG_MUSTFREE,
3899                                      message
3900                                      ("Last reference %q to %s storage %qnot %q before %q",
3901                                       sRef_unparse (sr),
3902                                       alkind_unparse (sRef_getAliasKind (sr)),
3903                                       sRef_unparseOpt (ar),
3904                                       cstring_makeLiteral (sRef_isKeep (sr) 
3905                                                            ? "transferred" : "released"),
3906                                       cstring_makeLiteral (isReturn 
3907                                                            ? "return" : "scope exit")),
3908                                      g_currentloc))
3909                                   {
3910                                     sRef_showRefLost (sr);
3911                                   }
3912                               }
3913                             else if (sRef_isNewRef (sr))
3914                               {
3915                                 if (optgenerror
3916                                     (FLG_MUSTFREE,
3917                                      message 
3918                                      ("%q %q not released before %q",
3919                                       cstring_makeLiteral 
3920                                       (alkind_isKillRef (sRef_getOrigAliasKind (sr))
3921                                        ? "Kill reference parameter" : "New reference"),
3922                                       uentry_getName (ce),
3923                                       cstring_makeLiteral (isReturn
3924                                                            ? "return" : "scope exit")),
3925                                      g_currentloc))
3926                                   {
3927                                     sRef_showAliasInfo (sr);
3928                                   }
3929                               }
3930                             else 
3931                               {
3932                                 if (ctype_isRealSU (sRef_getType (sr)))
3933                                   {
3934                                     checkStructDestroyed (sr, g_currentloc);
3935                                   }
3936                                 else
3937                                   {
3938                                     DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
3939
3940                                     if (optgenerror
3941                                         (FLG_MUSTFREE,
3942                                          message 
3943                                          ("%s storage %q not %q before %q",
3944                                           alkind_capName (sRef_getAliasKind (sr)),
3945                                           uentry_getName (ce),
3946                                           cstring_makeLiteral (sRef_isKeep (sr) 
3947                                                                ? "transferred" : "released"),
3948                                           cstring_makeLiteral (isReturn 
3949                                                                ? "return" : "scope exit")),
3950                                          g_currentloc))
3951                                       {
3952                                         sRef_showAliasInfo (sr);
3953                                         DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
3954                                       }
3955                                   }
3956                               }
3957                           }
3958                       }
3959                   else
3960                     {
3961                       ;
3962                     }
3963                 }
3964               else if (mustDefine && uentry_isOut (ce))
3965                 {
3966                   if (!ynm_toBoolStrict (sRef_isReadable (sr)))
3967                     {
3968                       voptgenerror 
3969                         (FLG_MUSTDEFINE,
3970                          message ("Out storage %q not defined before %q",
3971                                   uentry_getName (ce),
3972                                   cstring_makeLiteral 
3973                                   (isReturn ? "return" : "scope exit")),
3974                          g_currentloc);
3975                       
3976                       /* uentry_showWhereDeclared (ce); */
3977                     }
3978                 }
3979               else
3980                 {
3981                   ; 
3982                 }
3983               
3984               /*
3985               ** also check state is okay
3986               */
3987               
3988               if (usymtab_lexicalLevel () > functionScope
3989                   && uentry_isVariable (ce)
3990                   && (sRef_isLocalVar (sr)
3991                       && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
3992                 {
3993                   sRefSet ab = usymtab_aliasedBy (sr);
3994
3995                   /* should do something more efficient here */
3996
3997                   if (sRefSet_isEmpty (ab))
3998                     {
3999                       /* and no local ref */
4000                       DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4001                       checkLoseRef (ce);
4002                     }
4003                   else
4004                     {
4005                       ;
4006                     }
4007                   
4008                   sRefSet_free (ab);
4009                 }
4010               else 
4011                 {
4012                   ;
4013                 }
4014               
4015               checked = sRefSet_insert (checked, sr);
4016             }
4017         }
4018
4019       llassert (usymtab_isDefined (stab->env));
4020
4021       if (usymtab_isBranch (stab))
4022         {
4023           stab = usymtab_dropEnv (stab);
4024         }
4025       else
4026         {
4027           stab = stab->env;
4028         }
4029       
4030       llassert (stab != usymtab_undefined);
4031     } while (isReturn && (stab->lexlevel >= paramsScope));
4032   
4033   sRefSet_free (checked);
4034   
4035   /*
4036   ** for returns:
4037   **      all globals are appropriately defined
4038   **      all parameters are appropriately defined
4039   **      special clauses are followed
4040   */
4041
4042   if (isReturn || (utab->lexlevel == paramsScope))
4043     {
4044       uentry fcn = context_getHeader ();
4045       uentryList params = context_getParams ();
4046       globSet uglobs = context_getUsedGlobs ();
4047       globSet sglobs = context_getGlobs ();
4048             
4049       if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4050         { 
4051           aliasTable_checkGlobs (utab->aliases); 
4052         }
4053
4054       /*
4055       ** state clauses (ensures, defines, sets, allocates, releases) 
4056       */
4057       
4058       if (uentry_hasStateClauseList (fcn))
4059         {
4060           stateClauseList clauses = uentry_getStateClauseList (fcn);
4061
4062           stateClauseList_elements (clauses, cl)
4063             {
4064               if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl)) 
4065                 { 
4066                   if (stateClause_setsMetaState (cl)) 
4067                     {
4068                       sRefSet rfs = stateClause_getRefs (cl);
4069                       qual q = stateClause_getMetaQual (cl);
4070                       annotationInfo ainfo = qual_getAnnotationInfo (q);
4071                       metaStateInfo minfo = annotationInfo_getState (ainfo);
4072                       cstring key = metaStateInfo_getName (minfo);
4073                       int mvalue = annotationInfo_getValue (ainfo);
4074
4075                       DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4076
4077                       sRefSet_elements (rfs, el)
4078                         {
4079                           sRef base = sRef_getRootBase (el);
4080                           
4081                           if (sRef_isResult (base))
4082                             {
4083                               /* 
4084                               ** This is checked for return transfers. 
4085                               */
4086                               ;
4087                             }
4088                           else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4089                             {
4090                               sRef sr = sRef_updateSref (base);
4091                               sr = sRef_fixBase (el, sr);
4092                               
4093                               if (!sRef_checkMetaStateValue (sr, key, mvalue))
4094                                 {
4095                                   if (optgenerror 
4096                                       (FLG_STATETRANSFER,
4097                                        message
4098                                        ("Ensures clause not satisfied%q (state is %q): %q",
4099                                         sRef_isGlobalMarker (sr) 
4100                                         ? message ("") 
4101                                         : message (" by %q", sRef_unparse (sr)),
4102                                         stateValue_unparseValue (sRef_getMetaStateValue (sr, key), 
4103                                                                  minfo),
4104                                         stateClause_unparse (cl)),
4105                                        g_currentloc))
4106                                     {
4107                                       sRef_showMetaStateInfo (sr, key);
4108                                     }  
4109                                 }
4110                             }
4111                           else
4112                             {
4113                               if (sRef_isMeaningful (el))
4114                                 {
4115                                   BADBRANCH;
4116                                 }
4117                             }
4118                         } end_sRefSet_elements ;
4119                     }
4120                   else
4121                     {
4122                       /* evs - 2000 07 10 - added this */
4123                       sRefTest tst = stateClause_getPostTestFunction (cl);
4124                       sRefSet rfs = stateClause_getRefs (cl);
4125                       
4126                       sRefSet_elements (rfs, el)
4127                         {
4128                           sRef base = sRef_getRootBase (el);
4129                           
4130                           if (sRef_isResult (base))
4131                             {
4132                               /* 
4133                               ** This is checked for return transfers. 
4134                               */
4135
4136                               ; 
4137                             }
4138                           else if (sRef_isParam (base))
4139                             {
4140                               sRef sr = sRef_updateSref (base);
4141                               sr = sRef_fixBase (el, sr);
4142                               
4143                               if (tst != NULL && !tst (sr))
4144                                 {
4145                                   if (optgenerror 
4146                                       (stateClause_postErrorCode (cl),
4147                                        message ("%s storage %qcorresponds to "
4148                                                 "storage listed in %q clause",
4149                                                 stateClause_postErrorString (cl, sr),
4150                                                 sRef_unparseOpt (sr),
4151                                                 stateClause_unparseKind (cl)),
4152                                        g_currentloc))
4153                                     {
4154                                       sRefShower ss = stateClause_getPostTestShower (cl);
4155                                       
4156                                       if (ss != NULL)
4157                                         {
4158                                           ss (sr);
4159                                         }
4160
4161                                       DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4162                                     }  
4163                                 }
4164                             }
4165                           else
4166                             {
4167                               if (sRef_isMeaningful (el))
4168                                 {
4169                                   BADBRANCH;
4170                                 }
4171                             }
4172                         } end_sRefSet_elements ;
4173                     }
4174                 }
4175             } end_stateClauseList_elements ;
4176         }
4177       
4178       /*
4179       ** check parameters on return
4180       */
4181
4182       uentryList_elements (params, arg)
4183         {
4184           if (!uentry_isElipsisMarker (arg))
4185             {
4186               ctype rt = ctype_realType (uentry_getType (arg));
4187
4188               if (ctype_isMutable (rt) || ctype_isSU (rt))
4189                 {
4190                   uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4191                   DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4192                   checkParamReturn (param);
4193                 }
4194             }
4195         } end_uentryList_elements;
4196       
4197       DPRINTF (("Check global return: %s",
4198                 globSet_unparse (sglobs)));
4199
4200       globSet_allElements (sglobs, el)
4201         {
4202           sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4203           uentry current = sRef_getUentry (el);
4204
4205           DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4206                     uentry_unparseFull (current)));
4207           
4208           if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4209             {
4210               checkGlobalReturn (current, orig);
4211             }
4212         } end_globSet_allElements;
4213
4214       globSet_allElements (uglobs, el)
4215         {
4216           if (!globSet_member (sglobs, el))
4217             {
4218               uentry current = sRef_getUentry (el);
4219               
4220               if (uentry_isVariable (current)
4221                   && !uentry_isRealFunction (current))
4222                 {
4223                   checkGlobalReturn (current, sRef_undefined);
4224                 }
4225             }
4226         } end_globSet_allElements;
4227     }  
4228 }
4229
4230 void
4231 usymtab_quietExitScope (fileloc loc) 
4232    /*@globals utab, globtab, filetab; @*/ 
4233    /*@modifies utab@*/
4234 {
4235   usymtab t = utab->env;
4236
4237   if (utab->reftable != NULL)
4238     {
4239       int i;
4240
4241       for (i = 0; i < utab->nentries; i++)
4242         {
4243           uentry current = utab->entries[i];      
4244           uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4245
4246           uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4247         }
4248     }
4249
4250   llassert (t != NULL);
4251
4252   if (t->lexlevel > paramsScope)
4253     {
4254       t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4255       t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases, 
4256                                              t->lexlevel);
4257       utab->aliases = aliasTable_undefined;
4258     }
4259
4260   t->mustBreak = utab->mustBreak;
4261   t->exitCode = utab->exitCode;
4262
4263   usymtab_freeLevel (utab);
4264
4265   utab = t;
4266 }
4267
4268 /*
4269 ** Exit a scope with no checking, lose alias states.
4270 ** (When should this be used?)
4271 */
4272
4273 void usymtab_quietPlainExitScope (void)
4274      /*@globals utab, globtab, filetab@*/
4275      /*@modifies utab@*/
4276 {
4277   usymtab t = utab->env;
4278
4279   llassert (t != NULL);
4280   llassert (NOALIAS (utab->aliases, t->aliases));
4281   usymtab_freeLevel (utab);
4282   utab = t;
4283 }
4284
4285 void usymtab_exitScope (exprNode expr)
4286   /*@globals utab, filetab, globtab@*/
4287   /*@modifies utab, globtab@*/
4288 {
4289   usymtab ctab = usymtab_undefined;
4290   usymtab lctab = usymtab_undefined;
4291   bool mustReturn = exprNode_mustEscape (expr);
4292
4293   DPRINTF (("Exit scope"));
4294
4295   if (utab->kind == US_CBRANCH)
4296     {
4297       /*
4298       ** save the case branches, remove the first non-cbranch
4299       */
4300
4301       ctab = utab;
4302
4303       while (utab->kind == US_CBRANCH) 
4304         {
4305           lctab = utab;
4306           utab = utab->env;
4307           llassert (utab != GLOBAL_ENV);
4308         }
4309     }
4310   
4311   if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4312       || utab->kind == US_CBRANCH || utab->kind == US_SWITCH) {
4313    
4314     if (context_inMacro ()) {
4315       /* evs 2000-07-25 */
4316       /* Unparseable macro may end inside nested scope.  Deal with it. */
4317       
4318       llerror (FLG_SYNTAX, 
4319                message ("Problem parsing macro body of %s (unbalanced scopes). "
4320                         "Attempting to recover, recommend /*@notfunction@*/ before "
4321                         "macro definition.", 
4322                         context_inFunctionName ()));
4323       
4324       while (utab->kind == US_TBRANCH
4325              || utab->kind == US_FBRANCH
4326              || utab->kind == US_CBRANCH
4327              || utab->kind == US_SWITCH) 
4328         {
4329           utab = utab->env;
4330           llassert (utab != GLOBAL_ENV);
4331         }
4332     } else {
4333       llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4334       /*@-branchstate@*/ 
4335     } /*@=branchstate@*/
4336   }
4337
4338   /*
4339   ** check all variables in scope were used
4340   */
4341
4342   /*
4343   ** bogus errors if this is the normal inside a switch,
4344   ** since cases have not been merged yet.  Should probably
4345   ** still check this, but I'm too lazy at the moment...
4346   */
4347
4348   llassertfatal (utab->env != GLOBAL_ENV);
4349
4350   if (utab->env->kind != US_SWITCH)
4351     {
4352       usymtab_allUsed ();
4353     }
4354
4355   /*
4356   ** check aliasing: all only params are released (dead)
4357   **     definition: all out params are defined, all modified params 
4358   **                     are completely defined
4359   **
4360   ** NOTE: note for exiting paramsScope, since checkReturn should be
4361   ** called first.
4362   */
4363
4364   if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4365     {
4366       /*
4367       ** should only call this is end of scope is reachable...
4368       */
4369
4370       usymtab_checkFinalScope (FALSE);
4371     }
4372
4373   if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4374     {
4375       /*
4376       ** leaving a function, need to fix up globals
4377       */
4378
4379       uentryList params = context_getParams ();
4380       globSet    globs = context_getUsedGlobs ();
4381
4382                   
4383       uentryList_elements (params, ue)
4384         {
4385           uentry_fixupSref (ue);
4386         } end_uentryList_elements;
4387
4388       clearFunctionTypes ();
4389
4390       
4391       globSet_allElements (globs, el)
4392         {
4393           if (sRef_isCvar (el))
4394             {
4395               uentry current;
4396               int index = sRef_getScopeIndex (el);
4397               
4398               if (sRef_isFileStatic (el))
4399                 {
4400                   llassert (usymtab_isDefined (filetab));
4401                   current = usymtab_fetchIndex (filetab, index);
4402                 }
4403               else
4404                 {
4405                   current = usymtab_fetchIndex (globtab, index);
4406                 }
4407               
4408               if (uentry_isVariable (current))
4409                 {
4410                   uentry_fixupSref (current);
4411                 }
4412               else
4413                 {
4414                   sRef_clearDerived (uentry_getSref (current));
4415                 }
4416             }
4417         } end_globSet_allElements;
4418     }
4419   
4420   usymtab_quietExitScope (exprNode_loc (expr));
4421   
4422   if (lctab != usymtab_undefined)
4423     {
4424       /*@i@*/ lctab->env = utab;  
4425       /*@i@*/ utab = ctab;
4426     /*@-branchstate@*/ } /*@=branchstate@*/
4427 /*@-globstate@*/
4428 }
4429 /*@=globstate@*/
4430
4431 /*
4432 ** yikes!  don't let the '170 kids see this one...
4433 */
4434
4435 int
4436 uentry_directParamNo (uentry ue)
4437 {
4438   if (uentry_isVar (ue))
4439     {
4440       sRef sr = uentry_getSref (ue);
4441
4442       if (sRef_lexLevel (sr) == functionScope)
4443         {
4444           int index;
4445
4446           /*@access sRef@*/ 
4447           llassert (sr->info != NULL);
4448           llassert (sr->info->cvar != NULL);
4449           index = sr->info->cvar->index;
4450           /*@noaccess sRef@*/
4451
4452           if (index < uentryList_size (context_getParams ()))
4453             {
4454               return index;
4455             }
4456         }
4457     }
4458   return -1;
4459 }
4460
4461 /*@dependent@*/ /*@exposed@*/ uentry
4462   usymtab_getParam (int paramno)
4463   /*@globals utab@*/
4464 {
4465   /*
4466   ** requires in a function context (checked)
4467   **
4468   ** depends on no nested functions --- the function
4469   ** parameters are ALWAYS one scope inside the global scope
4470   ** and entered in order!
4471   */
4472   usymtab s = utab;
4473
4474   if (!context_inFunctionLike ())
4475     llfatalbug (message ("usymtab_getParam: not in function context: %q", 
4476                          context_unparse ()));
4477
4478   while (s->lexlevel > paramsScope) 
4479     {
4480       s = s->env;
4481     }
4482
4483   llassert (usymtab_isDefined (s));
4484
4485   if (paramno >= s->nentries)
4486     {
4487       /*  
4488       ** Parse errors lead to this. 
4489       */
4490
4491       uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4492                                            ctype_unknown);
4493       
4494       uentry_markOwned (err);
4495       return (err);
4496     }
4497
4498   return (s->entries[paramno]);
4499 }
4500
4501 static /*@dependent@*/ /*@exposed@*/ uentry 
4502 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4503 {
4504   uentry ue;
4505
4506   ue = usymtab_getRefNoisy (u, level, index);
4507
4508   if (uentry_isUndefined (ue))
4509     {
4510       llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4511                     index, level));
4512     }
4513   
4514   return ue;
4515 }
4516
4517 static /*@dependent@*/ /*@exposed@*/ usymtab 
4518   usymtab_dropEnv (/*@notnull@*/ usymtab s)
4519 {
4520   if (s->kind == US_CBRANCH)
4521     {
4522       usymtab t = s;
4523
4524       do 
4525         {
4526           t = s;
4527           s = s->env;
4528           llassert (s != GLOBAL_ENV);
4529         } while (s->kind == US_CBRANCH); 
4530       /* drop all cases (except in nested scopes */ 
4531
4532       s = t;
4533       llassert (s != GLOBAL_ENV);
4534     }
4535
4536   if (s->kind == US_FBRANCH)
4537     {
4538       s = s->env; /* skip the true branch */
4539       llassert (usymtab_isDefined (s));
4540       llassert (s->kind == US_TBRANCH);
4541     }
4542
4543   llassert (s != GLOBAL_ENV);
4544   s = s->env;
4545
4546   return s;
4547 }
4548
4549 /*@dependent@*/ /*@exposed@*/ uentry
4550   usymtab_getRefQuiet (int level, usymId index)
4551   /*@globals utab@*/
4552 {
4553   usymtab s = utab;
4554   
4555   
4556   llassert (s != NULL);
4557   llassert (index >= 0);
4558
4559   if (level > s->lexlevel)
4560     {            
4561       return uentry_undefined;
4562     }
4563
4564   llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d", 
4565                                         level, s->lexlevel)); 
4566
4567   while (s->lexlevel > level)
4568     {
4569       if (usymtab_isBranch (s))
4570         {
4571           int eindex = refTable_lookup (s, level, index);
4572
4573           if (eindex != NOT_FOUND)
4574             {
4575               return (s->entries[eindex]);
4576             }
4577         }
4578
4579       s = usymtab_dropEnv (s);
4580     }
4581
4582   while (usymtab_isBranch (s) && s->lexlevel == level)
4583     {
4584       int eindex = refTable_lookup (s, level, index);
4585       
4586       if (eindex != NOT_FOUND)
4587         {
4588           return (s->entries[eindex]);
4589         }
4590
4591       s = usymtab_dropEnv (s);
4592     }
4593  
4594   if (index >= s->nentries)
4595     {
4596       return uentry_undefined;
4597     }
4598
4599   llassert (!uentry_isUndefined (s->entries[index]));
4600
4601   return s->entries[index];
4602 }
4603
4604 static /*@dependent@*/ /*@exposed@*/ uentry
4605 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4606 {
4607   usymtab otab = s;
4608   uentry ue = uentry_undefined;
4609   
4610   llassert (index >= 0);
4611   
4612   while (s->lexlevel > level)
4613     {
4614       if (usymtab_isBranch (s))
4615         {
4616           int eindex = refTable_lookup (s, level, index);
4617
4618           if (eindex != NOT_FOUND)
4619             {
4620               ue = s->entries[eindex];
4621
4622               if (s != otab)
4623                 {
4624                   while (!usymtab_isBranch (otab))
4625                     {
4626                       otab = usymtab_dropEnv (otab);
4627                       llassert (otab != GLOBAL_ENV);
4628                     }
4629                 
4630                   if (refTable_lookup (otab, level, index) == NOT_FOUND)
4631                     {
4632                       ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4633                     }
4634                   else
4635                     {
4636                       ;
4637                     }
4638                 }
4639               
4640               return ue;
4641             }
4642         }
4643
4644       s = usymtab_dropEnv (s);
4645     }
4646
4647   llassert (usymtab_isDefined (s));
4648
4649   while (usymtab_isBranch (s) && s->lexlevel == level)
4650     {
4651       int eindex = refTable_lookup (s, level, index);
4652
4653       
4654       if (eindex != NOT_FOUND)
4655         {
4656           ue = s->entries[eindex];
4657           
4658           if (s != otab)
4659             {
4660               while (!usymtab_isBranch (otab))
4661                 {
4662                   otab = usymtab_dropEnv (otab);
4663                   llassert (otab != GLOBAL_ENV);
4664                 }
4665
4666               ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4667             }
4668           else
4669             {
4670               ;
4671             } 
4672
4673           return ue;
4674         }
4675
4676       s = usymtab_dropEnv (s);
4677           }
4678
4679   if (s->lexlevel == level && (index < s->nentries))
4680     {
4681       ue = s->entries[index];
4682       
4683       if (uentry_isValid (ue))
4684         {
4685           if (s != otab)
4686             {
4687               while (!usymtab_isBranch (otab))
4688                 {
4689                   otab = usymtab_dropEnv (otab);
4690                   
4691                   if (otab == GLOBAL_ENV)
4692                     {
4693                       return ue;
4694                     }
4695                 }
4696               
4697               ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4698             }
4699           else
4700             {
4701             }
4702         }
4703       
4704       return ue;
4705     }
4706
4707   
4708   if (index >= s->nentries)
4709     {
4710       return uentry_undefined;
4711     }
4712
4713   llassert (!uentry_isUndefined (s->entries[index]));
4714
4715   return s->entries[index];
4716 }
4717
4718 /*
4719 ** looking up entries
4720 **
4721 ** If entry is inside a branch, then copy it, and put it into 
4722 ** the branch table.
4723 */
4724
4725 static
4726 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4727 {
4728   refTable rt = ut->reftable;
4729   int i;
4730
4731   llassert (rt != NULL);
4732
4733   for (i = 0; i < ut->nentries; i++)
4734     {
4735       if (rt[i]->level == level && rt[i]->index == index)
4736         {
4737           return i;
4738         }
4739     }
4740   
4741   return NOT_FOUND;
4742 }
4743   
4744 static
4745 /*@only@*/ refentry refentry_create (int level, int index)
4746 {
4747   refentry r = (refentry) dmalloc (sizeof (*r));
4748
4749   r->level = level;
4750   r->index = index;
4751
4752   return r;
4753 }
4754
4755 static /*@dependent@*/ /*@exposed@*/ uentry
4756 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4757 {
4758   int eindex;
4759   usymtab ut = s;
4760
4761   if (ut->reftable == NULL) 
4762     {
4763       DPRINTF (("Adding ref entry without reftable: %s", k));
4764       return uentry_undefined;
4765     }
4766
4767   llassert (ut->reftable != NULL);
4768   
4769   while (s != GLOBAL_ENV)
4770     {
4771       eindex = usymtab_getIndex (s, k);
4772       
4773       if (eindex != NOT_FOUND)
4774         {
4775           uentry current = s->entries[eindex];
4776
4777           if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4778             {
4779               uentry ue;
4780
4781               DPRINTF (("Here: copying %s", uentry_unparse (current)));
4782               ue = uentry_copy (current);
4783               DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4784               usymtab_addEntryQuiet (ut, ue);
4785               DPRINTF (("Okay..."));
4786               
4787               if (s->reftable != NULL)
4788                 {
4789                   refentry ref = s->reftable[eindex];
4790                   
4791                   ut->reftable[ut->nentries - 1] 
4792                     = refentry_create (ref->level, ref->index);
4793                 }
4794               else
4795                 {
4796                   ut->reftable[ut->nentries - 1] 
4797                     = refentry_create (s->lexlevel, eindex);
4798                 }
4799               
4800               return (ue);
4801             }
4802           else
4803             {
4804               return (current);
4805             }
4806         }
4807
4808       s = usymtab_dropEnv (s);
4809     }
4810
4811   return uentry_undefined;
4812 }
4813
4814 static uentry usymtab_lookupAux (usymtab s, cstring k)
4815 {
4816   DPRINTF (("Lookup: %s", k));
4817
4818   while (s != GLOBAL_ENV)
4819     {
4820       int eindex = usymtab_getIndex (s, k);
4821
4822       if (eindex != NOT_FOUND)
4823         {
4824           uentry ret = s->entries[eindex];
4825 # if 0    
4826
4827           
4828           if (s->kind == US_TBRANCH 
4829               || s->kind == US_FBRANCH
4830               || s->kind == US_CBRANCH)
4831               /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4832             {
4833               uentry ret;
4834               DPRINTF (("Adding global ref entry: %s", k));
4835               ret = usymtab_addRefEntry (os, k);
4836               DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4837               return ret;
4838             }
4839
4840 # endif
4841           DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4842           return (ret);
4843         }
4844       
4845       if (s->kind == US_TBRANCH || s->kind == US_FBRANCH 
4846           || s->kind == US_CBRANCH)
4847         {
4848           /* why isn't this os??? */
4849           uentry ret = usymtab_addRefEntry (s, k);
4850           DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4851           return ret;
4852         }
4853       
4854       s = s->env;
4855     }
4856   
4857   return uentry_undefined;
4858 }
4859
4860 static /*@dependent@*/ /*@exposed@*/ uentry
4861 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
4862 {
4863   int eindex;
4864
4865   while (s != GLOBAL_ENV)
4866     {
4867       eindex = usymtab_getIndex (s, k);
4868       
4869       if (eindex != NOT_FOUND)
4870         {
4871           uentry ret = s->entries[eindex];
4872           return (ret);
4873         }
4874       
4875       if (noalt && usymtab_isBranch (s))
4876         {
4877           s = usymtab_dropEnv (s);
4878         }
4879       else
4880         {
4881           s = s->env;
4882         }
4883     }
4884
4885   return uentry_undefined;
4886 }
4887
4888 static /*@exposed@*/ /*@dependent@*/ uentry 
4889 usymtab_lookupQuiet (usymtab s, cstring k)
4890 {
4891   return usymtab_lookupQuietAux (s, k, FALSE);
4892 }
4893
4894 static /*@exposed@*/ /*@dependent@*/ uentry 
4895 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
4896 {
4897   return usymtab_lookupQuietAux (s, k, TRUE);
4898 }
4899
4900 /*@dependent@*/ /*@observer@*/ uentry
4901   usymtab_lookupSafe (cstring k)
4902   /*@globals utab@*/
4903 {
4904   DPRINTF (("Lookup safe: %s", k));
4905   return (usymtab_lookupAux (utab, k));
4906 }
4907
4908 uentry
4909   usymtab_lookupExpose (cstring k)
4910   /*@globals utab@*/
4911 {
4912   uentry ce = usymtab_lookupAux (utab, k);
4913
4914   if (uentry_isUndefined (ce))
4915     {
4916       llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
4917     }
4918
4919   if (uentry_isPriv (ce))
4920     {
4921       llfatalbug (message ("usymtab_lookup: private: *%s*", k));
4922     }
4923
4924   return ce;
4925 }
4926
4927 uentry usymtab_lookupExposeGlob (cstring k)
4928 {
4929   return (usymtab_lookupGlobSafe (k));
4930 }
4931
4932 uentry usymtab_lookupGlob (cstring k)
4933   /*@globals globtab@*/
4934 {
4935   uentry ce = usymtab_lookupAux (globtab, k);
4936
4937   if (uentry_isUndefined (ce))
4938     llfatalbug (message ("usymtab_lookup: not found: %s", k));
4939
4940   if (uentry_isPriv (ce))
4941     llfatalbug (message ("usymtab_lookup: private: %s", k));
4942
4943   return ce;
4944 }
4945
4946 /*@observer@*/ uentry
4947   usymtab_lookupGlobSafe (cstring k)
4948   /*@globals globtab@*/
4949 {
4950   uentry ce = usymtab_lookupAux (globtab, k);
4951
4952   return ce;
4953 }
4954
4955 uentry usymtab_lookupEither (cstring k)
4956    /*@globals utab@*/
4957 {
4958   uentry ce = usymtab_lookupSafe (k);
4959
4960   if (uentry_isUndefined (ce))
4961     llfatalerror (message ("usymtab_lookup: not found: %s", k));
4962
4963   return ce;
4964 }
4965
4966 # ifndef NOLCL
4967 ctype
4968 usymtab_lookupType (cstring k)
4969    /*@globals globtab@*/
4970 {
4971   usymId uid = usymtab_getTypeId (k);
4972
4973   if (uid == USYMIDINVALID)
4974     {
4975       llcontbug (message ("usymtab_lookupType: not found: %s", k));
4976       return ctype_unknown;
4977     }
4978   
4979   return (uentry_getRealType (usymtab_getTypeEntry (uid)));
4980 }
4981 # endif
4982
4983 ctype
4984 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
4985 {
4986   usymId uid = usymtab_getTypeId (k);
4987
4988   if (uid == USYMIDINVALID)
4989     {
4990       llcontbug (message ("usymtab_lookupType: not found: %s", k));
4991       return ctype_unknown; 
4992     }
4993   
4994   return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
4995 }
4996   
4997 /*
4998 ** if there is an unnamed lcl-specified struct tag matching
4999 ** the uentryList, return its datatype.  Otherwise, returns
5000 ** ctype_undefined.
5001 */
5002
5003 ctype
5004 usymtab_structFieldsType (uentryList f)
5005    /*@globals globtab@*/
5006 {
5007   return (usymtab_suFieldsType (f, TRUE));
5008 }
5009
5010 ctype
5011 usymtab_unionFieldsType (uentryList f)
5012    /*@globals globtab@*/
5013 {
5014   return (usymtab_suFieldsType (f, FALSE));
5015 }
5016
5017 static ctype
5018 usymtab_suFieldsType (uentryList f, bool isStruct)
5019   /*@globals globtab@*/
5020 {
5021   int i;
5022
5023   DPRINTF (("Fields: %s", uentryList_unparse (f)));
5024
5025   if (fileloc_isSpec (g_currentloc)) 
5026     {
5027       return (ctype_undefined);
5028     }
5029
5030   for (i = 0; i < globtab->nentries; i++)
5031     {
5032       uentry current = globtab->entries[i];
5033
5034       if ((isStruct 
5035            ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5036         {
5037           if (isFakeTag (uentry_rawName (current)))
5038             {
5039               ctype ct = uentry_getType (current);
5040               
5041               DPRINTF (("Check: %s", ctype_unparse (ct)));
5042
5043               if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5044                   && 
5045                   (uentry_isSpecified (current)
5046                    && uentryList_equivFields (f, ctype_getFields (ct))))
5047                 {
5048                   return uentry_getAbstractType (current);
5049                 }
5050               else
5051                 {
5052                   ;
5053                 }
5054             }
5055         }
5056     }
5057   
5058     return ctype_undefined;
5059 }
5060
5061 ctype
5062   usymtab_enumEnumNameListType (enumNameList f)
5063   /*@globals globtab@*/
5064 {
5065   int i;
5066
5067   for (i = 0; i < globtab->nentries; i++)
5068     {
5069       uentry current = globtab->entries[i];
5070
5071       if (uentry_isEnumTag (current))
5072         {
5073           if (isFakeTag (uentry_rawName (current)))
5074             {
5075               ctype ct = uentry_getType (current);
5076
5077               if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5078                 {
5079                   return uentry_getType (current);
5080                 }
5081             }
5082         }
5083     }
5084   
5085   return ctype_undefined;
5086 }
5087
5088 bool
5089 usymtab_exists (cstring k)
5090    /*@globals utab@*/
5091 {
5092   uentry ce = usymtab_lookupSafe (k);
5093   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5094 }
5095
5096 bool
5097 usymtab_existsReal (cstring k)
5098    /*@globals utab@*/
5099 {
5100   uentry ce = usymtab_lookupSafe (k);
5101
5102   return (!(uentry_isUndefined (ce)) 
5103           && !(uentry_isPriv (ce))
5104           && !(uentry_isExpandedMacro (ce)));
5105 }
5106
5107 bool
5108   usymtab_existsGlob (cstring k)
5109   /*@globals globtab@*/
5110 {
5111   uentry ce = usymtab_lookupAux (globtab, k);
5112
5113   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5114 }
5115
5116 # ifndef NOLCL
5117 bool
5118 usymtab_existsEither (cstring k)
5119   /*@globals utab@*/
5120 {
5121   uentry ce = usymtab_lookupAux (utab, k);
5122   
5123   return (uentry_isValid (ce));
5124 }
5125
5126 bool
5127   usymtab_existsGlobEither (cstring k)
5128   /*@globals globtab@*/
5129 {
5130   uentry ce = usymtab_lookupAux (globtab, k);
5131   
5132   return (uentry_isValid (ce));
5133 }
5134 # endif
5135
5136 bool
5137 usymtab_existsType (cstring k)
5138   /*@globals globtab@*/
5139 {
5140   uentry ce = usymtab_lookupAux (globtab, k);
5141
5142   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5143 }
5144
5145 bool
5146 usymtab_existsTypeEither (cstring k)
5147   /*@globals globtab@*/
5148 {
5149   uentry ce;
5150   ce = usymtab_lookupAux (globtab, k);
5151   return (uentry_isValid (ce) && uentry_isDatatype (ce));
5152 }
5153
5154 bool
5155 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5156 {
5157   cstring sname = makeStruct (k);
5158   uentry ce = usymtab_lookupAux (globtab, sname);
5159   cstring_free (sname);  
5160   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5161 }
5162
5163 bool
5164 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5165 {
5166   cstring uname = makeUnion (k);
5167   uentry ce = usymtab_lookupAux (globtab, uname);
5168
5169   cstring_free (uname);
5170
5171   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5172 }
5173
5174 bool
5175 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5176 {
5177   cstring ename = makeEnum (k);
5178   uentry ce = usymtab_lookupAux (globtab, ename);
5179
5180   cstring_free (ename);
5181   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5182 }
5183
5184 # ifndef NOLCL
5185 bool usymtab_existsVar (cstring k)
5186    /*@globals utab@*/
5187 {
5188   uentry ce = usymtab_lookupSafe (k);
5189
5190   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5191 }
5192 # endif
5193
5194 /*
5195 ** destructors
5196 */
5197
5198 static void
5199 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5200 {
5201   if (x != NULL)
5202     {
5203       int i;
5204
5205       for (i = 0; i < nentries; i++)
5206         {
5207           sfree (x[i]);
5208         }
5209       
5210       sfree (x);
5211     }
5212 }
5213   
5214 static void
5215 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5216   /*@globals globtab, utab, filetab@*/
5217 {
5218   int i;
5219
5220   aliasTable_free (u->aliases);
5221
5222   refTable_free (u->reftable, u->nentries);
5223
5224   if (u == filetab || u == globtab)
5225     {
5226       for (i = 0; i < u->nentries; i++)
5227         {
5228           uentry_freeComplete (u->entries[i]);
5229         }
5230     }
5231   else
5232     {
5233       for (i = 0; i < u->nentries; i++)
5234         {
5235           uentry_free (u->entries[i]);
5236         }
5237     }
5238
5239   guardSet_free (u->guards);
5240   sfree (u->entries);
5241
5242   if (u != globtab 
5243       && u != utab
5244       && u != filetab)
5245     {
5246       llassert (!cstringTable_isDefined (u->htable));
5247       sfree (u);
5248     }
5249
5250 /*@-mustfree@*/
5251 } /*@=mustfree@*/
5252
5253 static void
5254 usymtab_freeAux (/*@only@*/ usymtab u)
5255    /*@globals globtab, utab, filetab@*/
5256    /*@modifies u@*/
5257 {
5258   while (u != GLOBAL_ENV)
5259     {
5260       usymtab t = u->env;
5261       usymtab_freeLevel (u);
5262       u = t;
5263       /*@-branchstate@*/ 
5264     } 
5265   /*@=branchstate@*/
5266 }
5267
5268 void usymtab_free () 
5269   /*@globals killed utab, globtab, filetab@*/ 
5270   /*@modifies utab@*/
5271 {
5272   dbgfree = TRUE;
5273   usymtab_freeAux (utab);
5274 }
5275
5276 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5277 {
5278   return (utab->lexlevel);
5279 }
5280
5281 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5282 {
5283   return (utab == globtab);
5284 }
5285
5286 bool usymtab_inFileScope () /*@globals utab@*/
5287 {
5288   return (utab->lexlevel == fileScope);
5289 }
5290
5291 bool usymtab_inFunctionScope () /*@globals utab@*/
5292 {
5293   return (utab->lexlevel == functionScope);
5294 }
5295
5296 # ifndef NOLCL
5297 void
5298 usymtab_replaceEntry (uentry s)
5299   /*@globals utab, globtab@*/
5300   /*@modifies utab, s@*/
5301 {
5302   usymtab_replaceEntryAux (utab, s);
5303 }
5304 # endif
5305
5306 bool
5307 usymtab_matchForwardStruct (usymId u1, usymId u2)
5308    /*@globals globtab@*/
5309 {
5310   uentry ue1 = usymtab_getTypeEntry (u1);
5311   uentry ue2 = usymtab_getTypeEntry (u2);
5312
5313   if (uentry_isAnyTag (ue2))
5314     {
5315       ctype reptype = uentry_getType (ue1);
5316       
5317       if (ctype_isPointer (reptype))
5318         {
5319           ctype repbase = ctype_getBaseType (reptype);
5320   
5321           if (ctype_isUA (repbase))
5322             {
5323               typeId rtuid = ctype_typeId (repbase);
5324
5325               if (u2 == rtuid) return TRUE;
5326               
5327               if (usymId_isValid (rtuid))
5328                 {
5329                   reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5330                   
5331                   return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5332                 }
5333             }
5334         }
5335     }
5336   
5337   return FALSE;
5338 }
5339
5340 void usymtab_addGuards (guardSet guards)
5341   /*@modifies utab@*/
5342 {
5343   utab->guards = guardSet_union (utab->guards, guards);
5344   }
5345
5346 static bool usymtab_isGuardedAux (sRef s)
5347   /*@globals utab@*/
5348 {
5349   usymtab tab = utab;
5350   sRef base = sRef_getRootBase (s);
5351   int lowlevel = paramsScope;
5352   int baselevel = sRef_lexLevel (base);
5353
5354   if (sRef_isCvar (base))
5355     {
5356       lowlevel = baselevel;
5357       if (lowlevel < paramsScope) lowlevel = paramsScope;
5358     }
5359   
5360   while (tab->lexlevel >= lowlevel)
5361     {
5362       if (guardSet_isGuarded (tab->guards, s))
5363         {
5364           /*
5365           if (!sRef_definitelyNull (s))
5366             {
5367               sRef_setNotNull (s, fileloc_undefined);
5368             }
5369             */
5370           return TRUE;
5371         }
5372
5373       tab = usymtab_dropEnv (tab);
5374     }
5375   
5376   return FALSE;
5377 }
5378
5379 void usymtab_unguard (sRef s) /*@modifies utab@*/
5380 {
5381   usymtab tab = utab;
5382   sRef base = sRef_getRootBase (s);
5383   int lowlevel = paramsScope;
5384   int baselevel = sRef_lexLevel (base);
5385   
5386   if (sRef_isCvar (base))
5387     {
5388       lowlevel = baselevel;
5389       if (lowlevel < paramsScope) lowlevel = paramsScope;
5390     }
5391
5392   while (tab->lexlevel >= lowlevel)
5393     {
5394       if (guardSet_isGuarded (tab->guards, s))
5395         {
5396           guardSet_delete (tab->guards, s);
5397         }
5398       
5399       tab = usymtab_dropEnv (tab);
5400     }
5401 }
5402
5403 bool usymtab_isGuarded (sRef s)
5404 {
5405   
5406   return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5407 }
5408
5409 bool usymtab_isDefinitelyNull (sRef s)
5410 {
5411   return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5412 }
5413
5414 bool usymtab_isDefinitelyNullDeep (sRef s)
5415 {
5416   return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5417 }
5418
5419 static bool usymtab_isDefinitelyNullAux (sRef s)
5420   /*@globals utab@*/
5421 {
5422   usymtab tab = utab;
5423   sRef base = sRef_getRootBase (s);
5424   int  lowlevel = paramsScope;
5425   
5426   if (sRef_isCvar (base))
5427     {
5428       lowlevel = sRef_lexLevel (base);
5429       if (lowlevel < paramsScope) lowlevel = paramsScope;
5430     }
5431   
5432   while (tab->lexlevel >= lowlevel)
5433     {
5434       if (guardSet_mustBeNull (tab->guards, s))
5435         {
5436           return TRUE;
5437         }
5438       
5439       while (tab->kind == US_CBRANCH) 
5440         {
5441           tab = tab->env;
5442         }
5443
5444       llassert (usymtab_isDefined (tab));
5445
5446       if (tab->kind == US_FBRANCH)
5447         {
5448           tab = tab->env;
5449           llassert (tab->kind == US_TBRANCH);
5450         }
5451       
5452       tab = tab->env;
5453     }
5454
5455   return FALSE;
5456 }
5457
5458 void
5459 usymtab_printGuards ()
5460   /*@globals utab, globtab@*/
5461 {
5462   usymtab ttab = utab;
5463
5464   while (ttab != globtab)
5465     {
5466       llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5467                       guardSet_unparse (ttab->guards)));
5468       ttab = ttab->env;
5469     }
5470 }
5471
5472 void
5473 usymtab_displayAllUses ()
5474   /*@globals utab, globtab@*/
5475 {
5476   usymtab copy;
5477
5478   /* only in top scope */
5479   llassert (utab == globtab);
5480
5481   /* need a copy, so order is not messed up by sort! */  
5482   copy = usymtab_shallowCopy (globtab); 
5483   
5484   qsort (copy->entries, (size_t)copy->nentries, 
5485          sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5486
5487   usymtab_entries (copy, ue)
5488     {
5489       if (uentry_isValid (ue))
5490         {
5491           filelocList uses = uentry_getUses (ue);
5492           int size = filelocList_realSize (uses);
5493
5494           if (fileloc_isDefined (uentry_whereDefined (ue)) 
5495               && !fileloc_isLib (uentry_whereDefined (ue))
5496               && (size > 0))
5497             {
5498               llmsg (message ("%q (%q), %d use%&:\n   %q", 
5499                               uentry_getName (ue),
5500                               fileloc_unparse (uentry_whereDefined (ue)),
5501                               size, filelocList_unparseUses (uses)));
5502             }
5503         }
5504     } end_usymtab_entries;
5505   
5506   usymtab_shallowFree (copy);
5507 }
5508
5509 static /*@dependent@*/ /*@exposed@*/ usymtab
5510 usymtab_getFileTab ()
5511   /*@globals filetab@*/
5512 {
5513   llassert (filetab != NULL);
5514
5515   return filetab;
5516 }
5517
5518 /*@only@*/ cstring
5519 usymtab_unparseStack ()
5520   /*@globals utab@*/
5521 {
5522   return (usymtab_unparseStackTab (utab));
5523 }
5524  
5525 static /*@only@*/ cstring
5526 usymtab_unparseStackTab (usymtab t)
5527 {
5528   bool firstOne = TRUE;
5529   cstring ret = cstring_makeLiteral ("[");
5530
5531   while (t != GLOBAL_ENV)
5532     {
5533       if (firstOne)
5534         {
5535           ret = message ("%q %q", ret, usymtab_typeName (t));
5536           firstOne = FALSE;
5537         }
5538       else
5539         {
5540           ret = message ("%q, %q", ret, usymtab_typeName (t));
5541         }
5542       t = t->env;
5543     }
5544
5545   ret = message ("%q ]", ret);
5546   return ret;
5547 }
5548
5549 static /*@only@*/ cstring
5550 usymtab_typeName (/*@notnull@*/ usymtab t)
5551 {
5552   switch (t->kind)
5553     {
5554     case US_GLOBAL:  return cstring_makeLiteral ("global");
5555     case US_NORMAL:  return cstring_makeLiteral ("normal");
5556     case US_TBRANCH: return cstring_makeLiteral ("true");
5557     case US_FBRANCH: return cstring_makeLiteral ("false");
5558     case US_CBRANCH: return cstring_makeLiteral ("case");
5559     case US_SWITCH:  return cstring_makeLiteral ("switch");
5560     }
5561   
5562   BADEXIT;
5563 }
5564
5565 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5566   /*@modifies utab@*/
5567 {
5568   if (!sRef_similar (s, al))
5569     {
5570       usymtab_addForceMustAlias (s, al);
5571     }
5572 }
5573
5574 /*
5575 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5576 */
5577
5578 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5579   /*@modifies utab@*/
5580 {
5581   if (sRef_isMeaningful (s) 
5582       && sRef_isMeaningful (al)
5583       && !(sRef_isConst (s) || sRef_isConst (al))
5584       && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5585     {
5586       utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al); 
5587       DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5588
5589       /*
5590       ** for local variable, aliasing is symmetric 
5591       */
5592       
5593       if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5594         {
5595           utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s); 
5596         }
5597     }
5598   else
5599     {
5600       ;
5601     }
5602 }
5603
5604 void usymtab_clearAlias (sRef s)
5605   /*@modifies utab, s@*/
5606 {
5607   
5608   aliasTable_clearAliases (utab->aliases, s); 
5609 }
5610
5611 sRefSet usymtab_allAliases (sRef s)
5612    /*@globals utab@*/  
5613 {
5614   if (sRef_isMeaningful (s))
5615     {
5616       sRefSet ret;
5617             
5618       ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5619                                aliasTable_canAlias (utab->aliases, s));
5620       return (ret);
5621     }
5622   else
5623     {
5624       DPRINTF (("NOT A MEANINGFUL SREF!"));
5625       return sRefSet_undefined;
5626     }
5627 }
5628
5629 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5630      /*@globals utab@*/
5631 {
5632   if (sRef_isMeaningful (s))
5633     {
5634       sRefSet res = aliasTable_canAlias (utab->aliases, s);
5635       return res;
5636     }
5637   
5638   return sRefSet_undefined;
5639 }
5640
5641 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5642      /*@globals utab@*/
5643 {
5644   return (aliasTable_aliasedBy (utab->aliases, s));
5645 }
5646
5647 /*@only@*/ cstring usymtab_unparseAliases ()
5648   /*@globals utab@*/
5649 {
5650   return (aliasTable_unparse (utab->aliases));
5651 }
5652
5653 /*
5654 ** Debugging routines:
5655 **    okay to leak storage here, only for debugging 
5656 */
5657
5658 /*@-mustfree@*/ 
5659
5660 void
5661 usymtab_printOut (void)
5662   /*@globals utab@*/
5663 {
5664   int i;
5665   usymtab s = utab;
5666   int depth = 0;
5667   char *ind = mstring_copy ("               ");
5668
5669   fprintf (g_msgstream, "<<< [symbol table] >>>\n");
5670   
5671   while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5672     {
5673       cstring tname = usymtab_typeName (s);
5674
5675       if (depth < 5)
5676         {
5677           ind[depth * 3 + 1] = '\0';
5678         }
5679      
5680       fprintf (g_msgstream, "level: %d (%s)\n", s->lexlevel,
5681                cstring_toCharsSafe (tname));
5682
5683       cstring_free (tname);
5684
5685       for (i = 0; i < s->nentries; i++)
5686         {
5687           cstring us = uentry_unparseFull (s->entries[i]);
5688           fprintf (g_msgstream, "%s\n", cstring_toCharsSafe (us));
5689           cstring_free (us);
5690         }
5691       
5692       if (s->reftable != NULL && s->nentries > 0)
5693         {
5694           fprintf (g_msgstream, "\t<< Ref table >>\n");
5695
5696           for (i = 0; i < s->nentries; i++)
5697             {
5698               fprintf (g_msgstream, "\t%s %3d: %d, %d\n", ind, i, 
5699                        s->reftable[i]->level,
5700                        s->reftable[i]->index);
5701             }
5702         }
5703
5704       ind[depth * 3 + 1] = ' ';
5705       depth++;
5706       s = s->env;
5707     }
5708   fprintf (g_msgstream, "<<< end usymtab >>>\n");
5709   mstring_free (ind);
5710   return;
5711 }
5712
5713 void
5714 usymtab_printTypes ()
5715   /*@globals globtab@*/
5716 {
5717   usymtab_printAllAux (globtab);
5718 }
5719
5720 void 
5721 usymtab_printAll (void)
5722   /*@globals utab@*/
5723 {
5724   usymtab_printAllAux (utab);
5725 }
5726
5727 static void
5728 usymtab_printAllAux (usymtab s)
5729    /*@modifies g_msgstream@*/
5730 {
5731   int i;
5732   int depth = 0;
5733   char *ind = mstring_copy ("               ");
5734
5735   printf ("[[[ usymtab ]]]");
5736
5737   while (s != GLOBAL_ENV)
5738     {
5739       if (depth < 5)
5740         ind[depth * 3 + 1] = '\0';
5741       
5742       if (s->env == GLOBAL_ENV)
5743         {
5744           int looplow;
5745
5746           printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5747                   cstring_toCharsSafe (bool_unparse (s->mustBreak)), 
5748                   cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5749
5750           looplow = 0;
5751
5752           for (i = looplow; i < s->nentries; i++)
5753             {
5754               printf ("%s%3d. %s\n", ind, i, 
5755                       cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5756             }
5757         }
5758       else
5759         {
5760           printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5761                   cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5762                   cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5763
5764           for (i = 0; i < s->nentries; i++)
5765             {
5766               printf ("%s%3d %s\n", ind, i, 
5767                      cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5768             }
5769         }
5770       
5771       ind[depth * 3 + 1] = ' ';
5772       depth++;
5773       s = s->env;
5774     }
5775   printf ("----------\n");
5776 }
5777
5778 void
5779 usymtab_printComplete ()
5780   /*@globals utab@*/
5781 {
5782   int i;
5783   int depth = 0;
5784   char *ind = mstring_copy ("               ");
5785   usymtab s = utab;
5786
5787   while (s != GLOBAL_ENV)
5788     {
5789       if (depth < 5)
5790         {
5791           ind[depth * 3 + 1] = '\0';
5792         }
5793       
5794       if (s->env == GLOBAL_ENV)
5795         {
5796           int looplow;
5797
5798           printf ("level: %d\n", s->lexlevel);
5799
5800           looplow = 0;
5801
5802           for (i = looplow; i < s->nentries; i++)
5803             {
5804               printf ("%s%3d %s\n", ind, i, 
5805                       cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5806             }
5807         }
5808       else
5809         {
5810           printf ("level: %d\n", s->lexlevel);
5811           for (i = 0; i < s->nentries; i++)
5812             {
5813               printf ("%s%3d %s\n", ind, i, 
5814                      cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5815             }
5816         }
5817       
5818       ind[depth * 3 + 1] = ' ';
5819       depth++;
5820       s = s->env;
5821     }
5822
5823   printf ("----------\n");
5824   mstring_free (ind);
5825 }
5826
5827 static /*@only@*/ cstring /*@unused@*/ 
5828 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5829 {
5830   cstring c = message ("lexlevel: %d\n", s->lexlevel);
5831   int i;
5832
5833   for (i = 0; i < s->nentries; i++)
5834     {
5835       c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5836     }
5837
5838   c = message ("%q\n=========", c);
5839   return (c);
5840 }
5841
5842 static cstring /*@unused@*/ /*@only@*/ 
5843 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5844 {
5845   cstring c = message ("[%d/%s/%s] ", s->lexlevel, 
5846                        bool_unparse (s->mustBreak), 
5847                        exitkind_unparse (s->exitCode));
5848   int i;
5849
5850   for (i = 0; i < s->nentries; i++)
5851     {
5852       sRef sr = uentry_getSref (s->entries[i]);
5853
5854       if (i == 0)
5855         {
5856           c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]), 
5857                        sRef_isStateDefined (sr));
5858         }
5859       else
5860         {
5861           c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]), 
5862                        sRef_isStateDefined (sr));
5863         }
5864
5865     }
5866
5867   return (c);
5868 }
5869
5870 void
5871 usymtab_printLocal (void)
5872   /*@globals utab@*/
5873 {
5874   int i;
5875   usymtab s = utab;
5876
5877   printf ("lexlevel: %d\n", s->lexlevel);
5878
5879   for (i = 0; i < s->nentries; i++)
5880     {
5881       printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5882     }
5883   
5884   while (s->lexlevel > 1)
5885     {
5886       s = s->env;
5887     }
5888
5889   llassert (usymtab_isDefined (s));
5890
5891   printf ("Params:\n");
5892
5893   for (i = 0; i < s->nentries; i++)
5894     {
5895       printf ("%d: %s\n", i, 
5896               cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5897     }
5898 }
5899 /*@=mustfree@*/
5900
5901 static bool checkDistinctExternalName (uentry e)
5902   /*@globals globtab@*/
5903   /*@modifies *g_msgstream@*/
5904 {
5905   int checklen = context_getValue (FLG_EXTERNALNAMELEN);
5906   bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
5907   bool gotone = FALSE;
5908   bool extras = FALSE;
5909   bool hasError = FALSE;
5910   cstring name = uentry_rawName (e);
5911   usymtab st = globtab;
5912
5913   if (checklen == 0)
5914     {
5915       ;
5916     }
5917   else
5918     {
5919       if (uentry_isAnyTag (e)) 
5920         {
5921           checklen++;  /* the tag marker doesn't count */
5922         }
5923     }
5924
5925   usymtab_entries (st, oe)
5926     {
5927       if (uentry_sameObject (oe, e))
5928         {
5929           continue;
5930         }
5931
5932       if (checklen == 0)
5933         {
5934           if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
5935             {
5936               if (gotone)
5937                 {
5938                   extras = TRUE;
5939                   break;
5940                 }
5941               
5942               if (optgenerror 
5943                   (FLG_DISTINCTEXTERNALNAMES,
5944                    message 
5945                    ("External identifier %q is not distinguishable from %q "
5946                     "because alphabetical case is ignored",
5947                     uentry_getName (e),
5948                     uentry_getName (oe)),
5949                    uentry_whereLast (e)))
5950                 {
5951                   uentry_showWhereAny (oe);
5952                   uentry_setHasNameError (oe);
5953                   gotone = TRUE;
5954                 }
5955             }
5956         }
5957       else
5958         {
5959           if (ignorecase)
5960             {
5961               if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
5962                                                    name, checklen))
5963                 {
5964                   if (gotone)
5965                     {
5966                       extras = TRUE;
5967                       break;
5968                     }
5969                   
5970                   if (cstring_equalLen (uentry_rawName (oe), name, checklen))
5971                     {
5972                       if (optgenerror 
5973                           (FLG_DISTINCTEXTERNALNAMES,
5974                            /*@-sefparams@*/
5975                            message 
5976                            ("External identifier %q is not distinguishable from %q "
5977                             "in the first %d characters (%q)",
5978                             uentry_getName (e),
5979                             uentry_getName (oe),
5980                             checklen,
5981                             cstring_clip (uentry_getName (e), checklen)),
5982                            /*@=sefparams@*/
5983                            uentry_whereLast (e)))
5984                         {
5985                           uentry_showWhereAny (oe);
5986                           uentry_setHasNameError (oe);
5987                           gotone = TRUE;
5988                         }
5989                     }
5990                   else
5991                     {
5992                       if (gotone)
5993                         {
5994                           extras = TRUE;
5995                           break;
5996                         }
5997                       
5998                       if (optgenerror 
5999                           (FLG_DISTINCTEXTERNALNAMES,
6000                            message 
6001                            ("External identifier %q is not distinguishable from %q "
6002                             "in the first %d characters because alphabetical case "
6003                             "is ignored",
6004                             uentry_getName (e),
6005                             uentry_getName (oe),
6006                             checklen),
6007                            uentry_whereLast (e)))
6008                         {
6009                           uentry_showWhereAny (oe);
6010                           uentry_setHasNameError (oe);
6011                           gotone = TRUE;
6012                         }
6013                     }
6014                 }
6015             }
6016           else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6017             {
6018               if (gotone)
6019                 {
6020                   extras = TRUE;
6021                   break;
6022                 }
6023               
6024               if (optgenerror 
6025                   (FLG_DISTINCTEXTERNALNAMES,
6026                    /*@-sefparams@*/
6027                    message 
6028                    ("External identifier %q is not distinguishable from %q "
6029                     "in the first %d characters (%q)",
6030                     uentry_getName (e),
6031                     uentry_getName (oe),
6032                     checklen,
6033                     cstring_clip (uentry_getName (e), checklen)),
6034                    /*@=sefparams@*/
6035                    uentry_whereLast (e)))
6036                 {
6037                   uentry_showWhereAny (oe);
6038                   uentry_setHasNameError (oe);
6039                   gotone = TRUE;
6040                 }
6041             }
6042           else
6043             {
6044               ; /* okay */
6045             }
6046         }
6047     } end_usymtab_entries ;
6048
6049   hasError = gotone;
6050   
6051   if (extras)
6052     {
6053       llgenindentmsgnoloc
6054         (cstring_makeLiteral ("One or more additional "
6055                               "indistinguishable external "
6056                               "names not reported"));
6057     }
6058
6059   return hasError;
6060 }
6061
6062 static bool checkDistinctInternalName (uentry e)
6063   /*@globals utab@*/
6064   /*@modifies *g_msgstream@*/
6065 {
6066   usymtab ttab = utab;
6067   cstring name = uentry_rawName (e);
6068   int numchars = context_getValue (FLG_INTERNALNAMELEN);
6069   bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6070   bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6071
6072   if (uentry_isAnyTag (e) && (numchars != 0))
6073     {
6074       numchars++;  /* the tag marker doesn't count */
6075     }
6076   
6077   while (usymtab_isDefined (ttab))
6078     {
6079       usymtab_entries (ttab, oe)
6080         {
6081           if (uentry_sameObject (oe, e))
6082             {
6083               /*@innercontinue@*/ continue;
6084             }
6085
6086           switch (cstring_genericEqual
6087                   (name, uentry_rawName (oe),
6088                    numchars, caseinsensitive, lookalike))
6089             {
6090             case CGE_DISTINCT: /* okay */
6091               /*@switchbreak@*/ 
6092               break;
6093             case CGE_SAME:
6094               if (cstring_equal (name, uentry_rawName (oe)))
6095                 {
6096                   ; /* got a shadow error */
6097                 }
6098               else
6099                 {
6100                   if (optgenerror 
6101                       (FLG_DISTINCTINTERNALNAMES,
6102                        /*@-sefparams@*/
6103                        message 
6104                        ("Internal identifier %q is not distinguishable from %q "
6105                         "in the first %d characters (%q)",
6106                         uentry_getName (e),
6107                         uentry_getName (oe),
6108                         numchars,
6109                         cstring_clip (uentry_getName (e), numchars)),
6110                        /*@=sefparams@*/
6111                        uentry_whereLast (e)))
6112                     {
6113                       uentry_showWhereAny (oe);
6114                       uentry_setHasNameError (oe);
6115                       return TRUE;
6116                     }
6117                 }
6118               /*@switchbreak@*/
6119               break;
6120             case CGE_CASE:
6121               if (numchars == 0 
6122                   || (cstring_length (name) <= numchars))
6123                 {
6124                   if (optgenerror 
6125                       (FLG_DISTINCTINTERNALNAMES,
6126                        message 
6127                        ("Internal identifier %q is not distinguishable from %q "
6128                         "without case sensitivity",
6129                         uentry_getName (e),
6130                         uentry_getName (oe)),
6131                        uentry_whereLast (e)))
6132                     {
6133                       uentry_showWhereAny (oe);
6134                       uentry_setHasNameError (oe);
6135                       return TRUE;
6136                     }
6137                 }
6138               else 
6139                 {
6140                   if (optgenerror 
6141                       (FLG_DISTINCTINTERNALNAMES,
6142                        message 
6143                        ("Internal identifier %q is not distinguishable from %q "
6144                         "in the first %d characters without case sensitivity",
6145                         uentry_getName (e),
6146                         uentry_getName (oe),
6147                         numchars),
6148                        uentry_whereLast (e)))
6149                     {
6150                       uentry_showWhereAny (oe);
6151                       uentry_setHasNameError (oe);
6152                       return TRUE;
6153                     }
6154                 }
6155               /*@switchbreak@*/ 
6156               break;
6157             case CGE_LOOKALIKE:
6158               if (numchars == 0 
6159                   || (cstring_length (name) <= numchars))
6160                 {
6161                   if (optgenerror 
6162                       (FLG_DISTINCTINTERNALNAMES,
6163                        message 
6164                        ("Internal identifier %q is not distinguishable from %q "
6165                         "except by lookalike characters",
6166                         uentry_getName (e),
6167                         uentry_getName (oe)),
6168                        uentry_whereLast (e)))
6169                     {
6170                       uentry_showWhereAny (oe);
6171                       uentry_setHasNameError (oe);
6172                       return TRUE;
6173                     }
6174                 }
6175               else 
6176                 {
6177                   if (optgenerror 
6178                       (FLG_DISTINCTINTERNALNAMES,
6179                        message 
6180                        ("Internal identifier %q is not distinguishable from %q "
6181                         "in the first %d characters except by lookalike characters",
6182                         uentry_getName (e),
6183                         uentry_getName (oe),
6184                         numchars),
6185                        uentry_whereLast (e)))
6186                     {
6187                       uentry_showWhereAny (oe);
6188                       uentry_setHasNameError (oe);
6189                       return TRUE;
6190                     }
6191                 }
6192             }
6193         } end_usymtab_entries ;
6194       
6195       ttab = ttab->env;
6196     }
6197
6198   return FALSE;
6199 }
6200
6201 void usymtab_checkDistinctName (uentry e, int scope)
6202    /*@globals utab, globtab@*/
6203 {
6204   bool hasError = FALSE;
6205   fileloc where = uentry_whereLast (e);
6206
6207   if (!fileloc_isPreproc (where)  && !fileloc_isBuiltin (where))
6208     {
6209       if (scope == globScope)
6210         {
6211           if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6212             {
6213               hasError = checkDistinctExternalName (e);
6214             }
6215         }
6216       
6217       if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6218         {
6219           hasError = checkDistinctInternalName (e);
6220         }
6221     }
6222
6223   if (hasError)
6224     {
6225       uentry_setHasNameError (e);
6226     }
6227 }
6228
6229 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6230 {
6231   uentry ue;
6232
6233   ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6234   llassert (uentry_isValid (ue));
6235
6236   return uentry_getSref (ue);
6237 }
6238
This page took 0.555506 seconds and 5 git commands to generate.