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