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