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