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