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 
usymtab_getCurrentDepth(void)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 
recordFunctionType(uentry ue)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 
clearFunctionTypes(void)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 
usymtab_isBranch(usymtab u)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 
usymtab_mustBreak(usymtab s)212 static bool usymtab_mustBreak (usymtab s)
213 {
214   llassert (s != GLOBAL_ENV);
215   return (s->mustBreak);
216 }
217 
usymtab_mustEscape(usymtab s)218 static bool usymtab_mustEscape (usymtab s)
219 {
220   llassert (s != GLOBAL_ENV);
221   return (exitkind_mustEscape (s->exitCode));
222 }
223 
usymtab_setMustBreak()224 void usymtab_setMustBreak ()
225   /*@modifies utab@*/
226 {
227   llassert (utab != GLOBAL_ENV);
228   utab->mustBreak = TRUE;
229 }
230 
usymtab_setExitCode(exitkind ex)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 
usymtab_isAltDefinitelyNullDeep(sRef s)244 bool usymtab_isAltDefinitelyNullDeep (sRef s)
245 {
246   return (sRef_deepPred (usymtab_isAltDefinitelyNull, s));
247 }
248 
usymtab_isAltDefinitelyNull(sRef s)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
usymtab_create(uskind kind,usymtab env,bool nextlevel)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
usymtab_createRoot(void)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
usymtab_initMod(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
usymtab_destroyMod(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
usymtab_initGlobalMarker()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
usymtab_initBool()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
usymtab_grow(usymtab s)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
usymtab_addEntryQuiet(usymtab s,uentry e)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@*/
usymtab_addEntryBase(usymtab s,uentry e)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@*/
usymtab_addEntryAlways(usymtab s,uentry e)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
usymtab_addEntryAux(usymtab st,uentry e,bool isSref)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
usymtab_addEntry(uentry e)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
usymtab_addGlobalEntry(uentry e)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
usymtab_supEntryAux(usymtab st,uentry e,bool isSref)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
usymtab_replaceEntryAux(usymtab st,uentry e)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 
usymtab_supEntry(uentry e)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
usymtab_supEntryReturnAux(usymtab tab,uentry e,bool isref)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
usymtab_supEntryReturn(uentry e)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
usymtab_supEntrySrefReturn(uentry e)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
usymtab_supGlobalEntryReturn(uentry e)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
usymtab_supTypeEntry(uentry e)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
usymtab_supReturnTypeEntry(uentry e)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
usymtab_supAbstractTypeEntry(uentry e,bool dodef)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
usymtab_supExposedTypeEntry(uentry e,bool dodef)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
usymtab_supForwardTypeEntry(uentry e)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
usymtab_supEntrySref(uentry e)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 
usymtab_supGlobalEntry(uentry e)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
usymtab_supReturnFileEntry(uentry e)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
usymtab_inDeepScope()1399 usymtab_inDeepScope () /*@globals utab@*/
1400 {
1401   return (utab->lexlevel > paramsScope);
1402 }
1403 
1404 static usymId
usymtab_getIndex(usymtab s,cstring k)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
usymtab_fetchIndex(usymtab s,usymId ui)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
usymtab_getTypeId(cstring k)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
usymtab_lookupStructTag(cstring k)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
usymtab_lookupUnionTag(cstring k)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
usymtab_lookupEnumTag(cstring k)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
usymtab_getId(cstring k)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
usymtab_getEntryAux(usymtab s,usymId uid)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
usymtab_getGlobalEntry(usymId uid)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 
usymtab_getTypeEntry(typeId uid)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 
usymtab_getTypeEntrySafe(typeId uid)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 
usymtab_isBoolType(typeId uid)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 
usymtab_getTypeEntryName(typeId uid)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
usymtab_shallowCopy(usymtab s)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
usymtab_shallowFree(usymtab s)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 
usymtab_convertTypeId(typeId uid)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 
usymtab_convertId(usymId uid)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
usymtab_prepareDump(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 
usymtab_dump(FILE * fout)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 
usymtab_load(FILE * f)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
usymtab_enterFile()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
usymtab_exitFile()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
usymtab_enterScope()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
usymtab_handleParams(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
usymtab_enterFunctionScope(uentry fcn)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
usymtab_caseBranch(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
usymtab_switchBranch(exprNode s)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
usymtab_trueBranch(guardSet guards)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
usymtab_popTrueBranch(exprNode pred,exprNode expr,clause cl)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
usymtab_popCaseBranch()2556 usymtab_popCaseBranch () /*@modifies utab@*/
2557 {
2558   llassert (utab->kind == US_CBRANCH);
2559   usymtab_quietPlainExitScope ();
2560 }
2561 
2562 void
usymtab_popTrueExecBranch(exprNode pred,exprNode expr,clause cl)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
usymtab_popOrBranch(exprNode pred,exprNode expr)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
usymtab_newCase(exprNode pred,exprNode last)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
usymtab_popAndBranch(exprNode pred,exprNode expr)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
usymtab_exitSwitch(exprNode sw,bool allpaths)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
updateNullState(sRef el,usymtab ttab,usymtab ftab,bool trueGuard)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
usymtab_popBranches(exprNode pred,exprNode tbranch,exprNode fbranch,bool isOpt,clause cl)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 
usymtab_fixCases(void)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
usymtab_altBranch(guardSet guards)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
usymtab_allDefined(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 
usymtab_exportHeader(void)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 
usymtab_exportLocal(void)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
usymtab_allUsed(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
checkGlobalReturn(uentry glob,sRef orig)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 	      DPRINTF (("Here: %s / %s",
3822 			uentry_unparseFull (glob),
3823 			sRef_unparseFull (sr)));
3824 
3825 	      if (ctype_isRealPointer (uentry_getType (glob))
3826 		  && sRef_possiblyNull (sr)
3827 		  && !uentry_possiblyNull (glob))
3828 		{
3829 		  if (optgenerror
3830 		      (FLG_GLOBSTATE,
3831 		       message ("Function returns with non-null global %q "
3832 				"referencing null storage",
3833 				uentry_getName (glob)),
3834 		       g_currentloc))
3835 		    {
3836 		      sRef_showNullInfo (sr);
3837 		    }
3838 		}
3839 	      else
3840 		{
3841 		  DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3842 		  transferChecks_globalReturn (glob);
3843 		}
3844 	    }
3845 	}
3846     }
3847 }
3848 
3849 /*
3850 ** remember: check alias globals
3851 */
3852 
usymtab_checkFinalScope(bool isReturn)3853 void usymtab_checkFinalScope (bool isReturn)
3854   /*@globals utab@*/
3855 {
3856   bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3857   sRefSet checked = sRefSet_new ();
3858   usymtab stab = utab;
3859   int i;
3860 
3861   /*
3862   ** need to check all scopes out to function parameters.
3863   */
3864 
3865   do
3866     {
3867       for (i = 0; i < stab->nentries; i++)
3868 	{
3869 	  uentry ce = stab->entries[i];
3870 	  sRef sr = uentry_getSref (ce);
3871 	  sRef rb = sRef_getRootBase (sr);
3872 	  valueTable tvalues;
3873 
3874 	  /*
3875 	  ** Shouldn't check if shadow checked in deeper scope:
3876 	  */
3877 
3878 	  if (stab != utab)
3879 	    {
3880 	      uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3881 
3882 	      if (!uentry_sameObject (ce, oue))
3883 		{
3884 		  /* what if it is one an alternate branch? */
3885 		  /*@innercontinue@*/ continue;
3886 		}
3887 	    }
3888 
3889 	  DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3890 
3891 	  if (ctype_isFunction (uentry_getType (ce)))
3892 	    {
3893 	      /*@innercontinue@*/ continue;
3894 	    }
3895 
3896 	  if (uentry_isAnyParam (ce)
3897 	      || uentry_isRefParam (ce)
3898 	      || sRef_isFileOrGlobalScope (rb))
3899 	    {
3900 	      /* Don't do the loseref check...but should check state! */
3901 	      DPRINTF (("Skipping check 1"));
3902 	    }
3903 	  else if (sRef_isDefinitelyNull (sr)
3904 		   || usymtab_isDefinitelyNull (sr))
3905 	    {
3906 	      /*
3907 	      ** No state reference errors for definitely null references.
3908 	      */
3909 
3910 	      DPRINTF (("Skipping check 2"));
3911 	    }
3912 	  else
3913 	    {
3914 	      DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3915 			sRef_unparseFull (sr)));
3916 
3917 	      tvalues = sRef_getValueTable (sr);
3918 
3919 	      valueTable_elements (tvalues, fkey, fval) {
3920 		metaStateInfo minfo;
3921 		cstring msg = cstring_undefined;
3922 		int nval;
3923 
3924 		minfo = context_lookupMetaStateInfo (fkey);
3925 		llassert (metaStateInfo_isDefined (minfo));
3926 
3927 		if (stateValue_isError (fval)
3928 		    || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3929 		  {
3930 		    DPRINTF (("Skipping check 3"));
3931 		  }
3932 		else
3933 		  {
3934 		    DPRINTF (("Check: %s / %s / %s", fkey,
3935 			      metaStateInfo_unparse (minfo),
3936 			      stateValue_unparse (fval)));
3937 
3938 		    minfo = context_lookupMetaStateInfo (fkey);
3939 
3940 		    nval = stateCombinationTable_lookupLoseReference
3941 		      (metaStateInfo_getTransferTable (minfo),
3942 		       stateValue_getValue (fval), &msg);
3943 
3944 		    if (cstring_isDefined (msg))
3945 		      {
3946 			if (optgenerror
3947 			    (FLG_STATETRANSFER,
3948 			     message
3949 			     ("%s loses reference %q in invalid state %q (%s)",
3950 			      cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3951 			      uentry_getName (ce),
3952 			      stateValue_unparseValue (fval, minfo),
3953 			      msg),
3954 			     g_currentloc))
3955 			  {
3956 			    stateValue_show (fval, minfo);
3957 			  }
3958 			else
3959 			  {
3960 			    DPRINTF (("Suppressed transfer error: %s", msg));
3961 			  }
3962 		      }
3963 		  }
3964 	      } end_valueTable_elements;
3965 	    }
3966 
3967 	  DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3968 
3969 	  if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3970 	    {
3971 	      if (ctype_isRealSU (uentry_getType (ce))
3972 		  && !uentry_isAnyParam (ce)
3973 		  && !uentry_isRefParam (ce)
3974 		  && !uentry_isStatic (ce)
3975 		  && !sRef_isDependent (sr)
3976 		  && !sRef_isOwned (sr))
3977 		{
3978 		  sRefSet als = usymtab_allAliases (sr);
3979 
3980 		  if (sRefSet_isEmpty (als))
3981 		    {
3982 		      transferChecks_localDestroyed (sr, g_currentloc);
3983 		    }
3984 		  else
3985 		    {
3986 		      /* aliased, no problem */ ;
3987 		    }
3988 
3989 		  sRefSet_free (als);
3990 		}
3991 	      else if
3992 		(!uentry_isStatic (ce)
3993 		 && ((sRef_isNewRef (sr))
3994 		     || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3995 			   || sRef_isKeep (sr) || sRef_isOwned (sr))
3996 			  && !sRef_isDead (sr))
3997 			 && (!sRef_definitelyNull (sr))
3998 			 && (!usymtab_isDefinitelyNull (sr)))))
3999 		{
4000 		  bool hasError = TRUE;
4001 
4002 		  DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
4003 
4004 		  /*
4005 		  ** If its a scope exit, check if there is an alias.
4006 		  ** If so, make it only.  If not, there is an error.
4007 		  */
4008 
4009 		  if (!isReturn)
4010 		    {
4011 		      if (transferChecks_canLoseReference (sr, g_currentloc))
4012 			{
4013 			  DPRINTF (("Can lose!"));
4014 			  hasError = FALSE;
4015 			}
4016 		    }
4017 
4018 		  if (hasError)
4019 		    {
4020 		      if (sRef_hasLastReference (sr))
4021 			{
4022 			  sRef ar = sRef_getAliasInfoRef (sr);
4023 
4024 			  if (optgenerror
4025 			      (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4026 			       message
4027 			       ("Last reference %q to %s storage %qnot %q before %q",
4028 				sRef_unparse (sr),
4029 				alkind_unparse (sRef_getAliasKind (sr)),
4030 				sRef_unparseOpt (ar),
4031 				cstring_makeLiteral (sRef_isKeep (sr)
4032 						     ? "transferred" : "released"),
4033 				cstring_makeLiteral (isReturn
4034 						     ? "return" : "scope exit")),
4035 			       g_currentloc))
4036 			    {
4037 			      sRef_showRefLost (sr);
4038 			    }
4039 			}
4040 		      else if (sRef_isNewRef (sr))
4041 			{
4042 			  if (optgenerror
4043 			      (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4044 			       message
4045 			       ("%q %q not released before %q",
4046 				cstring_makeLiteral
4047 				(alkind_isKillRef (sRef_getOrigAliasKind (sr))
4048 				 ? "Kill reference parameter" : "New reference"),
4049 				uentry_getName (ce),
4050 				cstring_makeLiteral (isReturn
4051 						     ? "return" : "scope exit")),
4052 			       g_currentloc))
4053 			    {
4054 			      sRef_showAliasInfo (sr);
4055 			    }
4056 			}
4057 		      else
4058 			{
4059 			  if (ctype_isRealSU (sRef_getType (sr)))
4060 			    {
4061 			      transferChecks_structDestroyed (sr, g_currentloc);
4062 			    }
4063 			  else
4064 			    {
4065 			      if (optgenerror
4066 				  (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4067 				   message
4068 				   ("%s storage %q not %q before %q",
4069 				    alkind_capName (sRef_getAliasKind (sr)),
4070 				    uentry_getName (ce),
4071 				    cstring_makeLiteral (sRef_isKeep (sr)
4072 							 ? "transferred" : "released"),
4073 				    cstring_makeLiteral (isReturn
4074 							 ? "return" : "scope exit")),
4075 				   g_currentloc))
4076 				{
4077 				  sRef_showAliasInfo (sr);
4078 				  DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4079 				}
4080 			    }
4081 			}
4082 		    }
4083 		}
4084 	      else
4085 		{
4086 		  ;
4087 		}
4088 	    }
4089 
4090 	  if (mustDefine && uentry_isOut (ce))
4091 	    {
4092 	      /* No error if its dead (either only or error already reported */
4093 	      if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4094 		{
4095 		  voptgenerror
4096 		    (FLG_MUSTDEFINE,
4097 		     message ("Out storage %q not defined before %q",
4098 			      uentry_getName (ce),
4099 			      cstring_makeLiteral
4100 			      (isReturn ? "return" : "scope exit")),
4101 		     g_currentloc);
4102 
4103 		  DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4104 		}
4105 	    }
4106 
4107 	  /*
4108 	  ** also check state is okay
4109 	  */
4110 
4111 	  if (usymtab_lexicalLevel () > functionScope
4112 	      && uentry_isVariable (ce)
4113 	      && (sRef_isLocalVar (sr)
4114 		  && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4115 	    {
4116 	      sRefSet ab = usymtab_aliasedBy (sr);
4117 
4118 	      /* should do something more efficient here */
4119 
4120 	      if (sRefSet_isEmpty (ab))
4121 		{
4122 		  /* and no local ref */
4123 		  DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4124 		  transferChecks_loseReference (ce);
4125 		}
4126 	      else
4127 		{
4128 		  ;
4129 		}
4130 
4131 	      sRefSet_free (ab);
4132 	    }
4133 	  else
4134 	    {
4135 	      ;
4136 	    }
4137 
4138 	  checked = sRefSet_insert (checked, sr);
4139 	}
4140 
4141       llassert (usymtab_isDefined (stab->env));
4142 
4143       if (usymtab_isBranch (stab))
4144 	{
4145 	  stab = usymtab_dropEnv (stab);
4146 	}
4147       else
4148 	{
4149 	  stab = stab->env;
4150 	}
4151 
4152       llassert (stab != usymtab_undefined);
4153     } while (isReturn && (stab->lexlevel >= paramsScope));
4154 
4155   sRefSet_free (checked);
4156 
4157   /*
4158   ** for returns:
4159   **      all globals are appropriately defined
4160   **      all parameters are appropriately defined
4161   **      special clauses are followed
4162   */
4163 
4164   if (isReturn || (utab->lexlevel == paramsScope))
4165     {
4166       uentry fcn = context_getHeader ();
4167       uentryList params = context_getParams ();
4168       globSet uglobs = context_getUsedGlobs ();
4169       globSet sglobs = context_getGlobs ();
4170 
4171       if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4172 	{
4173 	  aliasTable_checkGlobs (utab->aliases);
4174 	}
4175 
4176       /*
4177       ** state clauses (ensures, defines, sets, allocates, releases)
4178       */
4179 
4180       if (uentry_hasStateClauseList (fcn))
4181 	{
4182 	  stateClauseList clauses = uentry_getStateClauseList (fcn);
4183 
4184 	  stateClauseList_elements (clauses, cl)
4185 	    {
4186 	      if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4187 		{
4188 		  if (stateClause_setsMetaState (cl))
4189 		    {
4190 		      sRefSet rfs = stateClause_getRefs (cl);
4191 		      qual q = stateClause_getMetaQual (cl);
4192 		      annotationInfo ainfo = qual_getAnnotationInfo (q);
4193 		      metaStateInfo minfo = annotationInfo_getState (ainfo);
4194 		      cstring key = metaStateInfo_getName (minfo);
4195 		      int mvalue = annotationInfo_getValue (ainfo);
4196 
4197 		      DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4198 
4199 		      sRefSet_elements (rfs, el)
4200 			{
4201 			  sRef base = sRef_getRootBase (el);
4202 
4203 			  if (sRef_isResult (base))
4204 			    {
4205 			      /*
4206 			      ** This is checked for return transfers.
4207 			      */
4208 			      ;
4209 			    }
4210 			  else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4211 			    {
4212 			      sRef sr = sRef_updateSref (base);
4213 			      sr = sRef_fixBase (el, sr);
4214 
4215 			      if (!sRef_checkMetaStateValue (sr, key, mvalue))
4216 				{
4217 				  if (optgenerror
4218 				      (FLG_STATETRANSFER,
4219 				       message
4220 				       ("Ensures clause not satisfied%q (state is %q): %q",
4221 					sRef_isGlobalMarker (sr)
4222 					? message ("")
4223 					: message (" by %q", sRef_unparse (sr)),
4224 					stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4225 								 minfo),
4226 					stateClause_unparse (cl)),
4227 				       g_currentloc))
4228 				    {
4229 				      sRef_showMetaStateInfo (sr, key);
4230 				    }
4231 				}
4232 			    }
4233 			  else
4234 			    {
4235 			      if (sRef_isMeaningful (el))
4236 				{
4237 				  BADBRANCH;
4238 				}
4239 			    }
4240 			} end_sRefSet_elements ;
4241 		    }
4242 		  else
4243 		    {
4244 		      /* evs - 2000 07 10 - added this */
4245 		      sRefTest tst = stateClause_getPostTestFunction (cl);
4246 		      sRefSet rfs = stateClause_getRefs (cl);
4247 
4248 		      sRefSet_elements (rfs, el)
4249 			{
4250 			  sRef base = sRef_getRootBase (el);
4251 
4252 			  if (sRef_isResult (base))
4253 			    {
4254 			      /*
4255 			      ** This is checked for return transfers.
4256 			      */
4257 
4258 			      ;
4259 			    }
4260 			  else if (sRef_isParam (base))
4261 			    {
4262 			      sRef sr = sRef_updateSref (base);
4263 			      sr = sRef_fixBase (el, sr);
4264 
4265 			      if (tst != NULL && !tst (sr))
4266 				{
4267 				  if (optgenerror
4268 				      (stateClause_postErrorCode (cl),
4269 				       message ("%s storage %qcorresponds to "
4270 						"storage listed in %q clause",
4271 						stateClause_postErrorString (cl, sr),
4272 						sRef_unparseOpt (sr),
4273 						stateClause_unparseKind (cl)),
4274 				       g_currentloc))
4275 				    {
4276 				      sRefShower ss = stateClause_getPostTestShower (cl);
4277 
4278 				      if (ss != NULL)
4279 					{
4280 					  ss (sr);
4281 					}
4282 
4283 				      DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4284 				    }
4285 				}
4286 			    }
4287 			  else
4288 			    {
4289 			      if (sRef_isMeaningful (el))
4290 				{
4291 				  BADBRANCH;
4292 				}
4293 			    }
4294 			} end_sRefSet_elements ;
4295 		    }
4296 		}
4297 	    } end_stateClauseList_elements ;
4298 	}
4299 
4300       /*
4301       ** check parameters on return
4302       */
4303 
4304       uentryList_elements (params, arg)
4305 	{
4306 	  if (!uentry_isElipsisMarker (arg))
4307 	    {
4308 	      ctype rt = ctype_realType (uentry_getType (arg));
4309 
4310 	      if (ctype_isMutable (rt) || ctype_isSU (rt))
4311 		{
4312 		  uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4313 		  DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4314 		  transferChecks_paramReturn (param);
4315 		}
4316 	    }
4317 	} end_uentryList_elements;
4318 
4319       DPRINTF (("Check global return: %s",
4320 		globSet_unparse (sglobs)));
4321 
4322       globSet_allElements (sglobs, el)
4323 	{
4324 	  sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4325 	  uentry current = sRef_getUentry (el);
4326 
4327 	  DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4328 		    uentry_unparseFull (current)));
4329 
4330 	  if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4331 	    {
4332 	      checkGlobalReturn (current, orig);
4333 	    }
4334 	} end_globSet_allElements;
4335 
4336       globSet_allElements (uglobs, el)
4337 	{
4338 	  if (!globSet_member (sglobs, el))
4339 	    {
4340 	      uentry current = sRef_getUentry (el);
4341 
4342 	      if (uentry_isVariable (current)
4343 		  && !uentry_isRealFunction (current))
4344 		{
4345 		  checkGlobalReturn (current, sRef_undefined);
4346 		}
4347 	    }
4348 	} end_globSet_allElements;
4349     }
4350 }
4351 
4352 void
usymtab_quietExitScope(fileloc loc)4353 usymtab_quietExitScope (fileloc loc)
4354    /*@globals utab, globtab, filetab; @*/
4355    /*@modifies utab@*/
4356 {
4357   usymtab t = utab->env;
4358 
4359   DPRINTF (("Quiet exit scope [%p]", utab));
4360 
4361   if (utab->reftable != NULL)
4362     {
4363       int i;
4364 
4365       for (i = 0; i < utab->nentries; i++)
4366 	{
4367 	  uentry current = utab->entries[i];
4368 	  uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4369 
4370 	  uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4371 	}
4372     }
4373 
4374   llassert (t != NULL);
4375 
4376   if (t->lexlevel > paramsScope)
4377     {
4378       t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4379       t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4380 					     t->lexlevel);
4381       utab->aliases = aliasTable_undefined;
4382     }
4383 
4384   t->mustBreak = utab->mustBreak;
4385   t->exitCode = utab->exitCode;
4386 
4387   DPRINTF (("Free level [%p]", utab));
4388   usymtab_freeLevel (utab);
4389 
4390   utab = t;
4391 
4392 # ifdef DEBUGSPLINT
4393   usymtab_checkAllValid ();
4394 # endif
4395 }
4396 
4397 /*
4398 ** Exit a scope with no checking, lose alias states.
4399 ** (When should this be used?)
4400 */
4401 
usymtab_quietPlainExitScope(void)4402 void usymtab_quietPlainExitScope (void)
4403      /*@globals utab, globtab, filetab@*/
4404      /*@modifies utab@*/
4405 {
4406   usymtab t = utab->env;
4407 
4408   llassert (t != NULL);
4409   llassert (NOALIAS (utab->aliases, t->aliases));
4410   usymtab_freeLevel (utab);
4411   utab = t;
4412 }
4413 
usymtab_exitScope(exprNode expr)4414 void usymtab_exitScope (exprNode expr)
4415   /*@globals utab, filetab, globtab@*/
4416   /*@modifies utab, globtab@*/
4417 {
4418   usymtab ctab = usymtab_undefined;
4419   usymtab lctab = usymtab_undefined;
4420   bool mustReturn = exprNode_mustEscape (expr);
4421 
4422   DPRINTF (("Exit scope [%p]", utab));
4423 
4424   if (utab->kind == US_CBRANCH)
4425     {
4426       /*
4427       ** save the case branches, remove the first non-cbranch
4428       */
4429 
4430       ctab = utab;
4431 
4432       while (utab->kind == US_CBRANCH)
4433 	{
4434 	  lctab = utab;
4435 	  utab = utab->env;
4436 	  llassert (utab != GLOBAL_ENV);
4437 	}
4438     }
4439 
4440   if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4441       || utab->kind == US_CBRANCH || utab->kind == US_SWITCH)
4442     {
4443       if (context_inMacro ())
4444 	{
4445 	  /* evs 2000-07-25 */
4446 	  /* Unparseable macro may end inside nested scope.  Deal with it. */
4447 
4448 	  llerror (FLG_SYNTAX,
4449 		   message ("Problem parsing macro body of %s (unbalanced scopes). "
4450 			    "Attempting to recover, recommend /*@notfunction@*/ before "
4451 			    "macro definition.",
4452 			    context_inFunctionName ()));
4453 
4454 	  while (utab->kind == US_TBRANCH
4455 		 || utab->kind == US_FBRANCH
4456 		 || utab->kind == US_CBRANCH
4457 		 || utab->kind == US_SWITCH)
4458 	    {
4459 	      utab = utab->env;
4460 	      llassert (utab != GLOBAL_ENV);
4461 	    }
4462 	} else
4463 	  {
4464 	    llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4465 	    /*@-branchstate@*/
4466 	  } /*@=branchstate@*/
4467     }
4468 
4469   /*
4470   ** check all variables in scope were used
4471   */
4472 
4473   /*
4474   ** bogus errors if this is the normal inside a switch,
4475   ** since cases have not been merged yet.  Should probably
4476   ** still check this, but I'm too lazy at the moment...
4477   */
4478 
4479   llassertfatal (utab->env != GLOBAL_ENV);
4480 
4481   if (utab->env->kind != US_SWITCH)
4482     {
4483       usymtab_allUsed ();
4484     }
4485 
4486   /*
4487   ** check aliasing: all only params are released (dead)
4488   **     definition: all out params are defined, all modified params
4489   **                     are completely defined
4490   **
4491   ** NOTE: note for exiting paramsScope, since checkReturn should be
4492   ** called first.
4493   */
4494 
4495   if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4496     {
4497       /*
4498       ** should only call this is end of scope is reachable...
4499       */
4500 
4501       usymtab_checkFinalScope (FALSE);
4502     }
4503 
4504   if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4505     {
4506       /*
4507       ** leaving a function, need to fix up globals
4508       */
4509 
4510       uentryList params = context_getParams ();
4511       globSet    globs = context_getUsedGlobs ();
4512 
4513       uentryList_elements (params, ue)
4514 	{
4515 	  uentry_fixupSref (ue);
4516 	} end_uentryList_elements;
4517 
4518       clearFunctionTypes ();
4519 
4520       DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4521 
4522       globSet_allElements (globs, el)
4523 	{
4524 	  DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4525 
4526 	  if (sRef_isCvar (el))
4527 	    {
4528 	      uentry current;
4529 	      usymId index = sRef_getScopeIndex (el);
4530 
4531 	      if (sRef_isFileStatic (el))
4532 		{
4533 		  llassert (usymtab_isDefined (filetab));
4534 		  current = usymtab_fetchIndex (filetab, index);
4535 		}
4536 	      else
4537 		{
4538 		  current = usymtab_fetchIndex (globtab, index);
4539 		}
4540 
4541 	      if (uentry_isVariable (current))
4542 		{
4543 		  DPRINTF (("Fixup: %s", uentry_unparse (current)));
4544 		  uentry_fixupSref (current);
4545 		}
4546 	      else
4547 		{
4548 		  DPRINTF (("Clear: %s", uentry_getSref (current)));
4549 		  sRef_clearDerived (uentry_getSref (current));
4550 		}
4551 	    }
4552 
4553 	  sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4554 	} end_globSet_allElements;
4555     }
4556 
4557   usymtab_quietExitScope (exprNode_loc (expr));
4558 
4559   if (lctab != usymtab_undefined)
4560     {
4561       /*@i@*/ lctab->env = utab;
4562       /*@i@*/ utab = ctab;
4563     /*@-branchstate@*/ } /*@=branchstate@*/
4564   /*@-globstate@*/
4565 
4566 
4567 # ifdef DEBUGSPLINT
4568   usymtab_checkAllValid ();
4569 # endif
4570 }
4571 /*@=globstate@*/
4572 
4573 /*
4574 ** yikes!  don't let the '170 kids see this one...
4575 */
4576 
4577 usymId
usymtab_directParamNo(uentry ue)4578 usymtab_directParamNo (uentry ue)
4579 {
4580   if (uentry_isVar (ue))
4581     {
4582       sRef sr = uentry_getSref (ue);
4583 
4584       if (sRef_lexLevel (sr) == functionScope)
4585 	{
4586 	  usymId index = sRef_getScopeIndex (sr);
4587 
4588 	  if (index < usymId_fromInt (uentryList_size (context_getParams ())))
4589 	    {
4590 	      return index;
4591 	    }
4592 	}
4593     }
4594   return usymId_invalid;
4595 }
4596 
4597 /*@dependent@*/ /*@exposed@*/ uentry
usymtab_getParam(int paramno)4598   usymtab_getParam (int paramno)
4599   /*@globals utab@*/
4600 {
4601   /*
4602   ** requires in a function context (checked)
4603   **
4604   ** depends on no nested functions --- the function
4605   ** parameters are ALWAYS one scope inside the global scope
4606   ** and entered in order!
4607   */
4608   usymtab s = utab;
4609 
4610   if (!context_inFunctionLike ())
4611     llfatalbug (message ("usymtab_getParam: not in function context: %q",
4612 			 context_unparse ()));
4613 
4614   while (s->lexlevel > paramsScope)
4615     {
4616       s = s->env;
4617     }
4618 
4619   llassert (usymtab_isDefined (s));
4620 
4621   if (paramno >= s->nentries)
4622     {
4623       /*
4624       ** Parse errors lead to this.
4625       */
4626 
4627       uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4628 					   ctype_unknown);
4629 
4630       uentry_markOwned (err);
4631       return (err);
4632     }
4633 
4634   return (s->entries[paramno]);
4635 }
4636 
4637 static /*@dependent@*/ /*@exposed@*/ uentry
usymtab_getRefTab(usymtab u,int level,usymId index)4638 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4639 {
4640   uentry ue;
4641 
4642   ue = usymtab_getRefNoisy (u, level, index);
4643 
4644   if (uentry_isUndefined (ue))
4645     {
4646       llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4647 		    index, level));
4648     }
4649 
4650   return ue;
4651 }
4652 
4653 static /*@dependent@*/ /*@exposed@*/ usymtab
usymtab_dropEnv(usymtab s)4654   usymtab_dropEnv (/*@notnull@*/ usymtab s)
4655 {
4656   if (s->kind == US_CBRANCH)
4657     {
4658       usymtab t = s;
4659 
4660       do
4661 	{
4662 	  t = s;
4663 	  s = s->env;
4664 	  llassert (s != GLOBAL_ENV);
4665 	} while (s->kind == US_CBRANCH);
4666       /* drop all cases (except in nested scopes */
4667 
4668       s = t;
4669       llassert (s != GLOBAL_ENV);
4670     }
4671 
4672   if (s->kind == US_FBRANCH)
4673     {
4674       s = s->env; /* skip the true branch */
4675       llassert (usymtab_isDefined (s));
4676       llassert (s->kind == US_TBRANCH);
4677     }
4678 
4679   llassert (s != GLOBAL_ENV);
4680   s = s->env;
4681 
4682   return s;
4683 }
4684 
4685 /*@dependent@*/ /*@exposed@*/ uentry
usymtab_getRefQuiet(int level,usymId index)4686   usymtab_getRefQuiet (int level, usymId index)
4687   /*@globals utab@*/
4688 {
4689   usymtab s = utab;
4690 
4691 
4692   llassert (s != NULL);
4693   llassert (index >= 0);
4694 
4695   if (level > s->lexlevel)
4696     {
4697       return uentry_undefined;
4698     }
4699 
4700   llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4701 					level, s->lexlevel));
4702 
4703   while (s->lexlevel > level)
4704     {
4705       if (usymtab_isBranch (s))
4706 	{
4707 	  int eindex = refTable_lookup (s, level, index);
4708 
4709 	  if (eindex != NOT_FOUND)
4710 	    {
4711 	      return (s->entries[eindex]);
4712 	    }
4713 	}
4714 
4715       s = usymtab_dropEnv (s);
4716     }
4717 
4718   while (usymtab_isBranch (s) && s->lexlevel == level)
4719     {
4720       int eindex = refTable_lookup (s, level, index);
4721 
4722       if (eindex != NOT_FOUND)
4723 	{
4724 	  return (s->entries[eindex]);
4725 	}
4726 
4727       s = usymtab_dropEnv (s);
4728     }
4729 
4730   if (index >= usymId_fromInt (s->nentries))
4731     {
4732       return uentry_undefined;
4733     }
4734 
4735   llassert (!uentry_isUndefined (s->entries[index]));
4736 
4737   return s->entries[index];
4738 }
4739 
4740 static /*@dependent@*/ /*@exposed@*/ uentry
usymtab_getRefNoisy(usymtab s,int level,usymId index)4741 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4742 {
4743   usymtab otab = s;
4744   uentry ue = uentry_undefined;
4745 
4746   llassert (index >= 0);
4747 
4748   while (s->lexlevel > level)
4749     {
4750       if (usymtab_isBranch (s))
4751 	{
4752 	  int eindex = refTable_lookup (s, level, index);
4753 
4754 	  if (eindex != NOT_FOUND)
4755 	    {
4756 	      ue = s->entries[eindex];
4757 
4758 	      if (s != otab)
4759 		{
4760 		  while (!usymtab_isBranch (otab))
4761 		    {
4762 		      otab = usymtab_dropEnv (otab);
4763 		      llassert (otab != GLOBAL_ENV);
4764 		    }
4765 
4766 		  if (refTable_lookup (otab, level, index) == NOT_FOUND)
4767 		    {
4768 		      ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4769 		    }
4770 		  else
4771 		    {
4772 		      ;
4773 		    }
4774 		}
4775 
4776 	      return ue;
4777 	    }
4778 	}
4779 
4780       s = usymtab_dropEnv (s);
4781     }
4782 
4783   llassert (usymtab_isDefined (s));
4784 
4785   while (usymtab_isBranch (s) && s->lexlevel == level)
4786     {
4787       int eindex = refTable_lookup (s, level, index);
4788 
4789       if (eindex != NOT_FOUND)
4790 	{
4791 	  ue = s->entries[eindex];
4792 
4793 	  if (s != otab)
4794 	    {
4795 	      while (!usymtab_isBranch (otab))
4796 		{
4797 		  otab = usymtab_dropEnv (otab);
4798 		  llassert (otab != GLOBAL_ENV);
4799 		}
4800 
4801 	      ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4802 	    }
4803 	  else
4804 	    {
4805 	      ;
4806 	    }
4807 
4808 	  return ue;
4809 	}
4810 
4811       s = usymtab_dropEnv (s);
4812           }
4813 
4814   if (s->lexlevel == level && (index < usymId_fromInt (s->nentries)))
4815     {
4816       ue = s->entries[index];
4817 
4818       if (uentry_isValid (ue))
4819 	{
4820 	  if (s != otab)
4821 	    {
4822 	      while (!usymtab_isBranch (otab))
4823 		{
4824 		  otab = usymtab_dropEnv (otab);
4825 
4826 		  if (otab == GLOBAL_ENV)
4827 		    {
4828 		      return ue;
4829 		    }
4830 		}
4831 
4832 	      ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4833 	    }
4834 	  else
4835 	    {
4836 	    }
4837 	}
4838 
4839       return ue;
4840     }
4841 
4842 
4843   if (index >= usymId_fromInt (s->nentries))
4844     {
4845       return uentry_undefined;
4846     }
4847 
4848   llassert (!uentry_isUndefined (s->entries[index]));
4849 
4850   return s->entries[index];
4851 }
4852 
4853 /*
4854 ** looking up entries
4855 **
4856 ** If entry is inside a branch, then copy it, and put it into
4857 ** the branch table.
4858 */
4859 
4860 static
refTable_lookup(usymtab ut,int level,usymId index)4861 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, usymId index)
4862 {
4863   refTable rt = ut->reftable;
4864   int i;
4865 
4866   llassert (rt != NULL);
4867 
4868   for (i = 0; i < ut->nentries; i++)
4869     {
4870       if (rt[i]->level == level && rt[i]->index == usymId_toInt (index))
4871 	{
4872 	  return i;
4873 	}
4874     }
4875 
4876   return NOT_FOUND;
4877 }
4878 
4879 static
refentry_create(int level,int index)4880 /*@only@*/ refentry refentry_create (int level, int index)
4881 {
4882   refentry r = (refentry) dmalloc (sizeof (*r));
4883 
4884   r->level = level;
4885   r->index = index;
4886 
4887   return r;
4888 }
4889 
4890 static /*@dependent@*/ /*@exposed@*/ uentry
usymtab_addRefEntry(usymtab s,cstring k)4891 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4892 {
4893   usymtab ut = s;
4894 
4895   if (ut->reftable == NULL)
4896     {
4897       DPRINTF (("Adding ref entry without reftable: %s", k));
4898       return uentry_undefined;
4899     }
4900 
4901   llassert (ut->reftable != NULL);
4902 
4903   while (s != GLOBAL_ENV)
4904     {
4905       usymId eindex = usymtab_getIndex (s, k);
4906 
4907       if (usymtab_indexFound (eindex))
4908 	{
4909 	  uentry current = s->entries[eindex];
4910 
4911 	  if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4912 	    {
4913 	      uentry ue;
4914 
4915 	      DPRINTF (("Here: copying %s", uentry_unparse (current)));
4916 	      if (uentry_isNonLocal (current))
4917 		{
4918 		  ue = uentry_copy (current);
4919 		}
4920 	      else
4921 		{
4922 		  ue = uentry_copyNoSave (current);
4923 		}
4924 
4925 	      DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4926 	      usymtab_addEntryQuiet (ut, ue);
4927 	      DPRINTF (("Okay..."));
4928 
4929 	      if (s->reftable != NULL)
4930 		{
4931 		  refentry ref = s->reftable[eindex];
4932 
4933 		  ut->reftable[ut->nentries - 1]
4934 		    = refentry_create (ref->level, ref->index);
4935 		}
4936 	      else
4937 		{
4938 		  ut->reftable[ut->nentries - 1]
4939 		    = refentry_create (s->lexlevel, usymId_toInt (eindex));
4940 		}
4941 
4942 	      return (ue);
4943 	    }
4944 	  else
4945 	    {
4946 	      return (current);
4947 	    }
4948 	}
4949 
4950       s = usymtab_dropEnv (s);
4951     }
4952 
4953   return uentry_undefined;
4954 }
4955 
usymtab_lookupAux(usymtab s,cstring k)4956 static uentry usymtab_lookupAux (usymtab s, cstring k)
4957 {
4958   DPRINTF (("Lookup: %s", k));
4959 
4960   while (s != GLOBAL_ENV)
4961     {
4962       usymId eindex = usymtab_getIndex (s, k);
4963 
4964       if (usymtab_indexFound (eindex))
4965 	{
4966 	  uentry ret = s->entries[eindex];
4967 # if 0
4968 
4969 
4970 	  if (s->kind == US_TBRANCH
4971 	      || s->kind == US_FBRANCH
4972 	      || s->kind == US_CBRANCH)
4973 	      /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4974 	    {
4975 	      uentry ret;
4976 	      DPRINTF (("Adding global ref entry: %s", k));
4977 	      ret = usymtab_addRefEntry (os, k);
4978 	      DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4979 	      return ret;
4980 	    }
4981 
4982 # endif
4983 	  DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4984 	  return (ret);
4985 	}
4986 
4987       if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4988 	  || s->kind == US_CBRANCH)
4989 	{
4990 	  /* why isn't this os??? */
4991 	  uentry ret = usymtab_addRefEntry (s, k);
4992 	  DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4993 	  return ret;
4994 	}
4995 
4996       s = s->env;
4997     }
4998 
4999   return uentry_undefined;
5000 }
5001 
5002 static /*@dependent@*/ /*@exposed@*/ uentry
usymtab_lookupQuietAux(usymtab s,cstring k,bool noalt)5003 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
5004 {
5005   while (s != GLOBAL_ENV)
5006     {
5007       usymId eindex = usymtab_getIndex (s, k);
5008 
5009       if (usymtab_indexFound (eindex))
5010 	{
5011 	  uentry ret = s->entries[eindex];
5012 	  return (ret);
5013 	}
5014 
5015       if (noalt && usymtab_isBranch (s))
5016 	{
5017 	  s = usymtab_dropEnv (s);
5018 	}
5019       else
5020 	{
5021 	  llassert (s != NULL);
5022 	  s = s->env;
5023 	}
5024     }
5025 
5026   return uentry_undefined;
5027 }
5028 
5029 static /*@exposed@*/ /*@dependent@*/ uentry
usymtab_lookupQuiet(usymtab s,cstring k)5030 usymtab_lookupQuiet (usymtab s, cstring k)
5031 {
5032   return usymtab_lookupQuietAux (s, k, FALSE);
5033 }
5034 
5035 static /*@exposed@*/ /*@dependent@*/ uentry
usymtab_lookupQuietNoAlt(usymtab s,cstring k)5036 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
5037 {
5038   return usymtab_lookupQuietAux (s, k, TRUE);
5039 }
5040 
5041 /*@dependent@*/ /*@observer@*/ uentry
usymtab_lookupSafe(cstring k)5042   usymtab_lookupSafe (cstring k)
5043   /*@globals utab@*/
5044 {
5045   DPRINTF (("Lookup safe: %s", k));
5046   return (usymtab_lookupAux (utab, k));
5047 }
5048 
5049 /*@dependent@*/ /*@observer@*/ uentry
usymtab_lookupSafeScope(cstring k,int lexlevel)5050   usymtab_lookupSafeScope (cstring k, int lexlevel)
5051   /*@globals utab@*/
5052 {
5053   /*
5054   ** This is necessary to deal with shadowed variables that are referenced
5055   ** through aliases inside the shadowed scope.  It would be better if
5056   ** lookup could take an sRef as a parameter.
5057   */
5058 
5059   usymtab tab = utab;
5060 
5061   while (tab != GLOBAL_ENV && tab->lexlevel > lexlevel) {
5062     uentry ret = usymtab_lookupAux (tab, k);
5063 
5064     if (uentry_isValid (ret)) {
5065       sRef sr = uentry_getSref (ret);
5066 
5067       if (sRef_isCvar (sr) && sRef_lexLevel (sr) > lexlevel) {
5068 	tab = usymtab_dropEnv (tab);
5069       } else {
5070 	return ret;
5071       }
5072     }
5073   }
5074 
5075   return uentry_undefined;
5076 }
5077 
5078 uentry
usymtab_lookupExpose(cstring k)5079   usymtab_lookupExpose (cstring k)
5080   /*@globals utab@*/
5081 {
5082   uentry ce = usymtab_lookupAux (utab, k);
5083 
5084   if (uentry_isUndefined (ce))
5085     {
5086       llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5087     }
5088 
5089   if (uentry_isPriv (ce))
5090     {
5091       llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5092     }
5093 
5094   return ce;
5095 }
5096 
usymtab_lookupExposeGlob(cstring k)5097 uentry usymtab_lookupExposeGlob (cstring k)
5098 {
5099   return (usymtab_lookupGlobSafe (k));
5100 }
5101 
usymtab_lookupGlob(cstring k)5102 uentry usymtab_lookupGlob (cstring k)
5103   /*@globals globtab@*/
5104 {
5105   uentry ce = usymtab_lookupAux (globtab, k);
5106 
5107   if (uentry_isUndefined (ce))
5108     llfatalbug (message ("usymtab_lookup: not found: %s", k));
5109 
5110   if (uentry_isPriv (ce))
5111     llfatalbug (message ("usymtab_lookup: private: %s", k));
5112 
5113   DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5114   return ce;
5115 }
5116 
5117 /*@observer@*/ uentry
usymtab_lookupGlobSafe(cstring k)5118   usymtab_lookupGlobSafe (cstring k)
5119   /*@globals globtab@*/
5120 {
5121   uentry ce = usymtab_lookupAux (globtab, k);
5122   DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5123   return ce;
5124 }
5125 
usymtab_lookupEither(cstring k)5126 uentry usymtab_lookupEither (cstring k)
5127    /*@globals utab@*/
5128 {
5129   uentry ce = usymtab_lookupSafe (k);
5130 
5131   if (uentry_isUndefined (ce))
5132     llfatalerror (message ("usymtab_lookup: not found: %s", k));
5133 
5134   DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5135   return ce;
5136 }
5137 
5138 ctype
usymtab_lookupType(cstring k)5139 usymtab_lookupType (cstring k)
5140    /*@globals globtab@*/
5141 {
5142   typeId uid = usymtab_getTypeId (k);
5143 
5144   if (typeId_isInvalid (uid))
5145     {
5146       llcontbug (message ("usymtab_lookupType: not found: %s", k));
5147       return ctype_unknown;
5148     }
5149 
5150   return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5151 }
5152 
5153 ctype
usymtab_lookupAbstractType(cstring k)5154 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5155 {
5156   typeId uid = usymtab_getTypeId (k);
5157 
5158   if (typeId_isInvalid (uid))
5159     {
5160       llcontbug (message ("usymtab_lookupType: not found: %s", k));
5161       return ctype_unknown;
5162     }
5163 
5164   return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5165 }
5166 
5167 /*
5168 ** if there is an unnamed lcl-specified struct tag matching
5169 ** the uentryList, return its datatype.  Otherwise, returns
5170 ** ctype_undefined.
5171 */
5172 
5173 ctype
usymtab_structFieldsType(uentryList f)5174 usymtab_structFieldsType (uentryList f)
5175    /*@globals globtab@*/
5176 {
5177   return (usymtab_suFieldsType (f, TRUE));
5178 }
5179 
5180 ctype
usymtab_unionFieldsType(uentryList f)5181 usymtab_unionFieldsType (uentryList f)
5182    /*@globals globtab@*/
5183 {
5184   return (usymtab_suFieldsType (f, FALSE));
5185 }
5186 
5187 static ctype
usymtab_suFieldsType(uentryList f,bool isStruct)5188 usymtab_suFieldsType (uentryList f, bool isStruct)
5189   /*@globals globtab@*/
5190 {
5191   int i;
5192 
5193   DPRINTF (("Fields: %s", uentryList_unparse (f)));
5194 
5195   if (fileloc_isSpec (g_currentloc))
5196     {
5197       return (ctype_undefined);
5198     }
5199 
5200   for (i = 0; i < globtab->nentries; i++)
5201     {
5202       uentry current = globtab->entries[i];
5203 
5204       if ((isStruct
5205 	   ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5206 	{
5207 	  if (isFakeTag (uentry_rawName (current)))
5208 	    {
5209 	      ctype ct = uentry_getType (current);
5210 
5211 	      DPRINTF (("Check: %s", ctype_unparse (ct)));
5212 
5213 	      if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5214 		  &&
5215 		  (uentry_isSpecified (current)
5216 		   && uentryList_equivFields (f, ctype_getFields (ct))))
5217 		{
5218 		  return uentry_getAbstractType (current);
5219 		}
5220 	      else
5221 		{
5222 		  ;
5223 		}
5224 	    }
5225 	}
5226     }
5227 
5228     return ctype_undefined;
5229 }
5230 
5231 ctype
usymtab_enumEnumNameListType(enumNameList f)5232   usymtab_enumEnumNameListType (enumNameList f)
5233   /*@globals globtab@*/
5234 {
5235   int i;
5236 
5237   for (i = 0; i < globtab->nentries; i++)
5238     {
5239       uentry current = globtab->entries[i];
5240 
5241       if (uentry_isEnumTag (current))
5242 	{
5243 	  if (isFakeTag (uentry_rawName (current)))
5244 	    {
5245 	      ctype ct = uentry_getType (current);
5246 
5247 	      if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5248 		{
5249 		  return uentry_getType (current);
5250 		}
5251 	    }
5252 	}
5253     }
5254 
5255   return ctype_undefined;
5256 }
5257 
5258 bool
usymtab_exists(cstring k)5259 usymtab_exists (cstring k)
5260    /*@globals utab@*/
5261 {
5262   uentry ce = usymtab_lookupSafe (k);
5263   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5264 }
5265 
5266 bool
usymtab_existsReal(cstring k)5267 usymtab_existsReal (cstring k)
5268    /*@globals utab@*/
5269 {
5270   uentry ce = usymtab_lookupSafe (k);
5271 
5272   return (!(uentry_isUndefined (ce))
5273 	  && !(uentry_isPriv (ce))
5274 	  && !(uentry_isExpandedMacro (ce)));
5275 }
5276 
5277 bool
usymtab_existsGlob(cstring k)5278   usymtab_existsGlob (cstring k)
5279   /*@globals globtab@*/
5280 {
5281   uentry ce = usymtab_lookupAux (globtab, k);
5282 
5283   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5284 }
5285 
5286 bool
usymtab_existsEither(cstring k)5287 usymtab_existsEither (cstring k)
5288   /*@globals utab@*/
5289 {
5290   uentry ce = usymtab_lookupAux (utab, k);
5291 
5292   return (uentry_isValid (ce));
5293 }
5294 
5295 bool
usymtab_existsGlobEither(cstring k)5296   usymtab_existsGlobEither (cstring k)
5297   /*@globals globtab@*/
5298 {
5299   uentry ce = usymtab_lookupAux (globtab, k);
5300 
5301   return (uentry_isValid (ce));
5302 }
5303 
5304 bool
usymtab_existsType(cstring k)5305 usymtab_existsType (cstring k)
5306   /*@globals globtab@*/
5307 {
5308   uentry ce = usymtab_lookupAux (globtab, k);
5309 
5310   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5311 }
5312 
5313 bool
usymtab_existsTypeEither(cstring k)5314 usymtab_existsTypeEither (cstring k)
5315   /*@globals globtab@*/
5316 {
5317   uentry ce;
5318   ce = usymtab_lookupAux (globtab, k);
5319   return (uentry_isValid (ce) && uentry_isDatatype (ce));
5320 }
5321 
5322 bool
usymtab_existsStructTag(cstring k)5323 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5324 {
5325   cstring sname = makeStruct (k);
5326   uentry ce = usymtab_lookupAux (globtab, sname);
5327   cstring_free (sname);
5328   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5329 }
5330 
5331 bool
usymtab_existsUnionTag(cstring k)5332 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5333 {
5334   cstring uname = makeUnion (k);
5335   uentry ce = usymtab_lookupAux (globtab, uname);
5336 
5337   cstring_free (uname);
5338 
5339   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5340 }
5341 
5342 bool
usymtab_existsEnumTag(cstring k)5343 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5344 {
5345   cstring ename = makeEnum (k);
5346   uentry ce = usymtab_lookupAux (globtab, ename);
5347 
5348   cstring_free (ename);
5349   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5350 }
5351 
usymtab_existsVar(cstring k)5352 bool usymtab_existsVar (cstring k)
5353    /*@globals utab@*/
5354 {
5355   uentry ce = usymtab_lookupSafe (k);
5356 
5357   return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5358 }
5359 
5360 /*
5361 ** destructors
5362 */
5363 
5364 static void
refTable_free(refTable x,int nentries)5365 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5366 {
5367   if (x != NULL)
5368     {
5369       int i;
5370 
5371       for (i = 0; i < nentries; i++)
5372 	{
5373 	  sfree (x[i]);
5374 	}
5375 
5376       sfree (x);
5377     }
5378 }
5379 
5380 static void
usymtab_freeLevel(usymtab u)5381 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5382   /*@globals globtab, utab, filetab@*/
5383 {
5384   int i;
5385 
5386   DPRINTF (("Free level [%p]", u));
5387   aliasTable_free (u->aliases);
5388 
5389   refTable_free (u->reftable, u->nentries);
5390 
5391   if (u == filetab || u == globtab)
5392     {
5393       for (i = 0; i < u->nentries; i++)
5394 	{
5395 	  DPRINTF (("Free complete: %d", i));
5396 	  DPRINTF (("Uentry: %s", uentry_unparse (u->entries[i])));
5397 	  uentry_freeComplete (u->entries[i]);
5398 	  u->entries[i] = uentry_undefined;
5399 	}
5400     }
5401   else
5402     {
5403       for (i = 0; i < u->nentries; i++)
5404 	{
5405 	  uentry_free (u->entries[i]);
5406 	  u->entries[i] = uentry_undefined;
5407 	}
5408     }
5409 
5410   guardSet_free (u->guards);
5411   sfree (u->entries);
5412 
5413   if (u != globtab
5414       && u != utab
5415       && u != filetab)
5416     {
5417       llassert (!cstringTable_isDefined (u->htable));
5418     }
5419 
5420   sfree (u); /* evans 2002-07-12: was inside if */
5421 }
5422 
5423 static void
usymtab_freeAux(usymtab u)5424 usymtab_freeAux (/*@only@*/ usymtab u)
5425    /*@globals globtab, utab, filetab@*/
5426    /*@modifies u@*/
5427 {
5428   while (u != GLOBAL_ENV)
5429     {
5430       usymtab t = u->env;
5431       usymtab_freeLevel (u);
5432       u = t;
5433       /*@-branchstate@*/
5434     }
5435   /*@=branchstate@*/
5436 }
5437 
usymtab_free()5438 void usymtab_free ()
5439   /*@globals killed utab, globtab, filetab@*/
5440   /*@modifies utab@*/
5441 {
5442   dbgfree = TRUE;
5443   usymtab_freeAux (utab);
5444   utab = usymtab_undefined;
5445   /*@-globstate@*/
5446 } /*@=globstate@*/ /* Splint cannot tell that utab is killed */
5447 
usymtab_lexicalLevel(void)5448 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5449 {
5450   return (utab->lexlevel);
5451 }
5452 
usymtab_inGlobalScope()5453 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5454 {
5455   return (utab == globtab);
5456 }
5457 
usymtab_inFileScope()5458 bool usymtab_inFileScope () /*@globals utab@*/
5459 {
5460   return (utab->lexlevel == fileScope);
5461 }
5462 
usymtab_inFunctionScope()5463 bool usymtab_inFunctionScope () /*@globals utab@*/
5464 {
5465   return (utab->lexlevel == functionScope);
5466 }
5467 
5468 void
usymtab_replaceEntry(uentry s)5469 usymtab_replaceEntry (uentry s)
5470   /*@globals utab, globtab@*/
5471   /*@modifies utab, s@*/
5472 {
5473   usymtab_replaceEntryAux (utab, s);
5474 }
5475 
5476 bool
usymtab_matchForwardStruct(typeId u1,typeId u2)5477 usymtab_matchForwardStruct (typeId u1, typeId u2)
5478    /*@globals globtab@*/
5479 {
5480   uentry ue1 = usymtab_getTypeEntry (u1);
5481   uentry ue2 = usymtab_getTypeEntry (u2);
5482 
5483   if (uentry_isAnyTag (ue2))
5484     {
5485       ctype reptype = uentry_getType (ue1);
5486 
5487       if (ctype_isPointer (reptype))
5488 	{
5489 	  ctype repbase = ctype_getBaseType (reptype);
5490 
5491 	  if (ctype_isUA (repbase))
5492 	    {
5493 	      typeId rtuid = ctype_typeId (repbase);
5494 
5495 	      if (u2 == rtuid) return TRUE;
5496 
5497 	      if (typeId_isValid (rtuid))
5498 		{
5499 		  reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5500 		  return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5501 		}
5502 	    }
5503 	}
5504     }
5505 
5506   return FALSE;
5507 }
5508 
usymtab_addGuards(guardSet guards)5509 void usymtab_addGuards (guardSet guards)
5510   /*@modifies utab@*/
5511 {
5512   utab->guards = guardSet_union (utab->guards, guards);
5513   }
5514 
usymtab_isGuardedAux(sRef s)5515 static bool usymtab_isGuardedAux (sRef s)
5516   /*@globals utab@*/
5517 {
5518   usymtab tab = utab;
5519   sRef base = sRef_getRootBase (s);
5520   int lowlevel = paramsScope;
5521   int baselevel = sRef_lexLevel (base);
5522 
5523   if (sRef_isCvar (base))
5524     {
5525       lowlevel = baselevel;
5526       if (lowlevel < paramsScope) lowlevel = paramsScope;
5527     }
5528 
5529   while (tab->lexlevel >= lowlevel)
5530     {
5531       DPRINTF (("Is guarded? [%s] %s",
5532 		guardSet_unparse (tab->guards),
5533 		sRef_unparseFull (s)));
5534 
5535       if (guardSet_isGuarded (tab->guards, s))
5536 	{
5537 	  /*
5538 	  if (!sRef_definitelyNull (s))
5539 	    {
5540 	      sRef_setNotNull (s, fileloc_undefined);
5541 	    }
5542 	    */
5543 	  return TRUE;
5544 	}
5545 
5546       tab = usymtab_dropEnv (tab);
5547     }
5548 
5549   return FALSE;
5550 }
5551 
usymtab_unguard(sRef s)5552 void usymtab_unguard (sRef s) /*@modifies utab@*/
5553 {
5554   usymtab tab = utab;
5555   sRef base = sRef_getRootBase (s);
5556   int lowlevel = paramsScope;
5557   int baselevel = sRef_lexLevel (base);
5558 
5559   if (sRef_isCvar (base))
5560     {
5561       lowlevel = baselevel;
5562       if (lowlevel < paramsScope) lowlevel = paramsScope;
5563     }
5564 
5565   while (tab->lexlevel >= lowlevel)
5566     {
5567       if (guardSet_isGuarded (tab->guards, s))
5568 	{
5569 	  guardSet_delete (tab->guards, s);
5570 	}
5571 
5572       tab = usymtab_dropEnv (tab);
5573     }
5574 }
5575 
usymtab_isGuarded(sRef s)5576 bool usymtab_isGuarded (sRef s)
5577 {
5578   DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5579   return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5580 }
5581 
usymtab_isDefinitelyNull(sRef s)5582 bool usymtab_isDefinitelyNull (sRef s)
5583 {
5584   return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5585 }
5586 
usymtab_isDefinitelyNullDeep(sRef s)5587 bool usymtab_isDefinitelyNullDeep (sRef s)
5588 {
5589   return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5590 }
5591 
usymtab_isDefinitelyNullAux(sRef s)5592 static bool usymtab_isDefinitelyNullAux (sRef s)
5593   /*@globals utab@*/
5594 {
5595   usymtab tab = utab;
5596   sRef base = sRef_getRootBase (s);
5597   int  lowlevel = paramsScope;
5598 
5599   if (sRef_isCvar (base))
5600     {
5601       lowlevel = sRef_lexLevel (base);
5602       if (lowlevel < paramsScope) lowlevel = paramsScope;
5603     }
5604 
5605   while (tab->lexlevel >= lowlevel)
5606     {
5607       if (guardSet_mustBeNull (tab->guards, s))
5608 	{
5609 	  return TRUE;
5610 	}
5611 
5612       while (tab->kind == US_CBRANCH)
5613 	{
5614 	  tab = tab->env;
5615 	}
5616 
5617       llassert (usymtab_isDefined (tab));
5618 
5619       if (tab->kind == US_FBRANCH)
5620 	{
5621 	  tab = tab->env;
5622 	  llassert (tab->kind == US_TBRANCH);
5623 	}
5624 
5625       tab = tab->env;
5626     }
5627 
5628   return FALSE;
5629 }
5630 
5631 void
usymtab_printGuards()5632 usymtab_printGuards ()
5633   /*@globals utab, globtab@*/
5634 {
5635   usymtab ttab = utab;
5636 
5637   while (ttab != globtab)
5638     {
5639       llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5640 		      guardSet_unparse (ttab->guards)));
5641       ttab = ttab->env;
5642     }
5643 }
5644 
5645 void
usymtab_displayAllUses()5646 usymtab_displayAllUses ()
5647   /*@globals utab, globtab@*/
5648 {
5649   usymtab copy;
5650 
5651   /* only in top scope */
5652   llassert (utab == globtab);
5653 
5654   /* need a copy, so order is not messed up by sort! */
5655   copy = usymtab_shallowCopy (globtab);
5656 
5657   qsort (copy->entries, (size_t)copy->nentries,
5658 	 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5659 
5660   usymtab_entries (copy, ue)
5661     {
5662       if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5663 	{
5664 	  filelocList uses = uentry_getUses (ue);
5665 	  int size = filelocList_realSize (uses);
5666 
5667 	  if (fileloc_isDefined (uentry_whereDefined (ue))
5668 	      && !fileloc_isLib (uentry_whereDefined (ue))
5669 	      && (size > 0))
5670 	    {
5671 	      llmsg (message ("%q (%q), %d use%&:\n   %q",
5672 			      uentry_getName (ue),
5673 			      fileloc_unparse (uentry_whereDefined (ue)),
5674 			      size, filelocList_unparseUses (uses)));
5675 	    }
5676 	}
5677     } end_usymtab_entries;
5678 
5679   usymtab_shallowFree (copy);
5680 }
5681 
5682 static /*@dependent@*/ /*@exposed@*/ usymtab
usymtab_getFileTab()5683 usymtab_getFileTab ()
5684   /*@globals filetab@*/
5685 {
5686   llassert (filetab != NULL);
5687 
5688   return filetab;
5689 }
5690 
5691 /*@only@*/ cstring
usymtab_unparseStack()5692 usymtab_unparseStack ()
5693   /*@globals utab@*/
5694 {
5695   return (usymtab_unparseStackTab (utab));
5696 }
5697 
5698 static /*@only@*/ cstring
usymtab_unparseStackTab(usymtab t)5699 usymtab_unparseStackTab (usymtab t)
5700 {
5701   bool firstOne = TRUE;
5702   cstring ret = cstring_makeLiteral ("[");
5703 
5704   while (t != GLOBAL_ENV)
5705     {
5706       if (firstOne)
5707 	{
5708 	  ret = message ("%q %q", ret, usymtab_typeName (t));
5709 	  firstOne = FALSE;
5710 	}
5711       else
5712 	{
5713 	  ret = message ("%q, %q", ret, usymtab_typeName (t));
5714 	}
5715       t = t->env;
5716     }
5717 
5718   ret = message ("%q ]", ret);
5719   return ret;
5720 }
5721 
5722 static /*@only@*/ cstring
usymtab_typeName(usymtab t)5723 usymtab_typeName (/*@notnull@*/ usymtab t)
5724 {
5725   switch (t->kind)
5726     {
5727     case US_GLOBAL:  return cstring_makeLiteral ("global");
5728     case US_NORMAL:  return cstring_makeLiteral ("normal");
5729     case US_TBRANCH: return cstring_makeLiteral ("true");
5730     case US_FBRANCH: return cstring_makeLiteral ("false");
5731     case US_CBRANCH: return cstring_makeLiteral ("case");
5732     case US_SWITCH:  return cstring_makeLiteral ("switch");
5733     }
5734 
5735   BADEXIT;
5736 }
5737 
usymtab_addMustAlias(sRef s,sRef al)5738 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5739   /*@modifies utab@*/
5740 {
5741   if (!sRef_similar (s, al))
5742     {
5743       usymtab_addForceMustAlias (s, al);
5744     }
5745 }
5746 
5747 /*
5748 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5749 */
5750 
usymtab_addForceMustAlias(sRef s,sRef al)5751 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5752   /*@modifies utab@*/
5753 {
5754   /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5755   if (sRef_isMeaningful (s)
5756       && sRef_isMeaningful (al)
5757       && !(sRef_isConst (s) || sRef_isConst (al))
5758       && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5759     {
5760       utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5761       DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5762 
5763       /*
5764       ** for local variable, aliasing is symmetric
5765       */
5766 
5767       if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5768 	{
5769 	  utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5770 	}
5771     }
5772   else
5773     {
5774       DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5775       DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5776     }
5777 }
5778 
usymtab_addReallyForceMustAlias(sRef s,sRef al)5779 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5780   /*@modifies utab@*/
5781 {
5782   utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5783 }
5784 
usymtab_clearAlias(sRef s)5785 void usymtab_clearAlias (sRef s)
5786   /*@modifies utab, s@*/
5787 {
5788 
5789   aliasTable_clearAliases (utab->aliases, s);
5790 }
5791 
usymtab_allAliases(sRef s)5792 sRefSet usymtab_allAliases (sRef s)
5793    /*@globals utab@*/
5794 {
5795   if (sRef_isSomewhatMeaningful (s))
5796     {
5797       sRefSet ret;
5798 
5799       ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5800 			       aliasTable_canAlias (utab->aliases, s));
5801       return (ret);
5802     }
5803   else
5804     {
5805       DPRINTF (("NOT A MEANINGFUL SREF!"));
5806       return sRefSet_undefined;
5807     }
5808 }
5809 
usymtab_canAlias(sRef s)5810 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5811      /*@globals utab@*/
5812 {
5813   if (sRef_isSomewhatMeaningful (s))
5814     {
5815       sRefSet res = aliasTable_canAlias (utab->aliases, s);
5816       return res;
5817     }
5818 
5819   return sRefSet_undefined;
5820 }
5821 
usymtab_aliasedBy(sRef s)5822 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5823      /*@globals utab@*/
5824 {
5825   return (aliasTable_aliasedBy (utab->aliases, s));
5826 }
5827 
usymtab_unparseAliases()5828 /*@only@*/ cstring usymtab_unparseAliases ()
5829   /*@globals utab@*/
5830 {
5831   return (aliasTable_unparse (utab->aliases));
5832 }
5833 
5834 /*
5835 ** Debugging routines:
5836 **    okay to leak storage here, only for debugging
5837 */
5838 
5839 /*@-mustfree@*/
5840 
5841 void
usymtab_printOut(void)5842 usymtab_printOut (void)
5843   /*@globals utab@*/
5844 {
5845   int i;
5846   usymtab s = utab;
5847   int depth = 0;
5848   char *ind = mstring_copy ("               ");
5849 
5850   fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5851 
5852   while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5853     {
5854       cstring tname = usymtab_typeName (s);
5855 
5856       if (depth < 5)
5857 	{
5858 	  ind[depth * 3 + 1] = '\0';
5859 	}
5860 
5861       fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5862 	       cstring_toCharsSafe (tname));
5863 
5864       cstring_free (tname);
5865 
5866       for (i = 0; i < s->nentries; i++)
5867 	{
5868 	  cstring us = uentry_unparseFull (s->entries[i]);
5869 	  fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5870 	  cstring_free (us);
5871 	}
5872 
5873       if (s->reftable != NULL && s->nentries > 0)
5874 	{
5875 	  fprintf (g_warningstream, "\t<< Ref table >>\n");
5876 
5877 	  for (i = 0; i < s->nentries; i++)
5878 	    {
5879 	      fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5880 		       s->reftable[i]->level,
5881 		       s->reftable[i]->index);
5882 	    }
5883 	}
5884 
5885       ind[depth * 3 + 1] = ' ';
5886       depth++;
5887       s = s->env;
5888     }
5889   fprintf (g_warningstream, "<<< end usymtab >>>\n");
5890   mstring_free (ind);
5891   return;
5892 }
5893 
5894 void
usymtab_printTypes()5895 usymtab_printTypes ()
5896   /*@globals globtab@*/
5897 {
5898   usymtab_printAllAux (globtab);
5899 }
5900 
5901 void
usymtab_printAll(void)5902 usymtab_printAll (void)
5903   /*@globals utab@*/
5904 {
5905   usymtab_printAllAux (utab);
5906 }
5907 
5908 static void
usymtab_printAllAux(usymtab s)5909 usymtab_printAllAux (usymtab s)
5910    /*@modifies g_warningstream@*/
5911 {
5912   int i;
5913   int depth = 0;
5914   char *ind = mstring_copy ("               ");
5915 
5916   printf ("[[[ usymtab ]]]");
5917 
5918   while (s != GLOBAL_ENV)
5919     {
5920       if (depth < 5)
5921 	ind[depth * 3 + 1] = '\0';
5922 
5923       if (s->env == GLOBAL_ENV)
5924 	{
5925 	  int looplow;
5926 
5927 	  printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5928 		  cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5929 		  cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5930 
5931 	  looplow = 0;
5932 
5933 	  for (i = looplow; i < s->nentries; i++)
5934 	    {
5935 	      printf ("%s%3d. %s\n", ind, i,
5936 		      cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5937 	    }
5938 	}
5939       else
5940 	{
5941 	  printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5942 		  cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5943 		  cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5944 
5945 	  for (i = 0; i < s->nentries; i++)
5946 	    {
5947 	      printf ("%s%3d %s\n", ind, i,
5948 		     cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5949 	    }
5950 	}
5951 
5952       ind[depth * 3 + 1] = ' ';
5953       depth++;
5954       s = s->env;
5955     }
5956   printf ("----------\n");
5957 }
5958 
5959 void
usymtab_printComplete()5960 usymtab_printComplete ()
5961   /*@globals utab@*/
5962 {
5963   int i;
5964   int depth = 0;
5965   char *ind = mstring_copy ("               ");
5966   usymtab s = utab;
5967 
5968   while (s != GLOBAL_ENV)
5969     {
5970       if (depth < 5)
5971 	{
5972 	  ind[depth * 3 + 1] = '\0';
5973 	}
5974 
5975       if (s->env == GLOBAL_ENV)
5976 	{
5977 	  int looplow;
5978 
5979 	  printf ("level: %d\n", s->lexlevel);
5980 
5981 	  looplow = 0;
5982 
5983 	  for (i = looplow; i < s->nentries; i++)
5984 	    {
5985 	      printf ("%s%3d %s\n", ind, i,
5986 		      cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5987 	    }
5988 	}
5989       else
5990 	{
5991 	  printf ("level: %d\n", s->lexlevel);
5992 	  for (i = 0; i < s->nentries; i++)
5993 	    {
5994 	      printf ("%s%3d %s\n", ind, i,
5995 		     cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5996 	    }
5997 	}
5998 
5999       ind[depth * 3 + 1] = ' ';
6000       depth++;
6001       s = s->env;
6002     }
6003 
6004   printf ("----------\n");
6005   mstring_free (ind);
6006 }
6007 
6008 # ifdef S_SPLINT_S
6009 static /*@only@*/ cstring /*@unused@*/
usymtab_unparseLocalAux(usymtab s)6010 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
6011 {
6012   cstring c = message ("lexlevel: %d\n", s->lexlevel);
6013   int i;
6014 
6015   for (i = 0; i < s->nentries; i++)
6016     {
6017       c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
6018     }
6019 
6020   c = message ("%q\n=========", c);
6021   return (c);
6022 }
6023 
6024 static cstring /*@unused@*/ /*@only@*/
usymtab_unparseLocalList(usymtab s)6025 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
6026 {
6027   cstring c = message ("[%d/%s/%s] ", s->lexlevel,
6028 		       bool_unparse (s->mustBreak),
6029 		       exitkind_unparse (s->exitCode));
6030   int i;
6031 
6032   for (i = 0; i < s->nentries; i++)
6033     {
6034       sRef sr = uentry_getSref (s->entries[i]);
6035 
6036       if (i == 0)
6037 	{
6038 	  c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
6039 		       sRef_isStateDefined (sr));
6040 	}
6041       else
6042 	{
6043 	  c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
6044 		       sRef_isStateDefined (sr));
6045 	}
6046 
6047     }
6048 
6049   return (c);
6050 }
6051 # endif
6052 
6053 void
usymtab_printLocal(void)6054 usymtab_printLocal (void)
6055   /*@globals utab@*/
6056 {
6057   int i;
6058   usymtab s = utab;
6059 
6060   printf ("lexlevel: %d\n", s->lexlevel);
6061 
6062   for (i = 0; i < s->nentries; i++)
6063     {
6064       printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6065     }
6066 
6067   while (s->lexlevel > 1)
6068     {
6069       s = s->env;
6070     }
6071 
6072   llassert (usymtab_isDefined (s));
6073 
6074   printf ("Params:\n");
6075 
6076   for (i = 0; i < s->nentries; i++)
6077     {
6078       printf ("%d: %s\n", i,
6079 	      cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6080     }
6081 }
6082 /*@=mustfree@*/
6083 
checkDistinctExternalName(uentry e)6084 static bool checkDistinctExternalName (uentry e)
6085   /*@globals globtab@*/
6086   /*@modifies *g_warningstream@*/
6087 {
6088   size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6089   bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6090   bool gotone = FALSE;
6091   bool extras = FALSE;
6092   bool hasError = FALSE;
6093   cstring name = uentry_rawName (e);
6094   usymtab st = globtab;
6095 
6096   if (checklen == 0)
6097     {
6098       ;
6099     }
6100   else
6101     {
6102       if (uentry_isAnyTag (e))
6103 	{
6104 	  checklen++;  /* the tag marker doesn't count */
6105 	}
6106     }
6107 
6108   usymtab_entries (st, oe)
6109     {
6110       if (uentry_sameObject (oe, e))
6111 	{
6112 	  continue;
6113 	}
6114 
6115       if (checklen == 0)
6116 	{
6117 	  if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6118 	    {
6119 	      if (gotone)
6120 		{
6121 		  extras = TRUE;
6122 		  break;
6123 		}
6124 
6125 	      if (optgenerror
6126 		  (FLG_DISTINCTEXTERNALNAMES,
6127 		   message
6128 		   ("External identifier %q is not distinguishable from %q "
6129 		    "because alphabetical case is ignored",
6130 		    uentry_getName (e),
6131 		    uentry_getName (oe)),
6132 		   uentry_whereLast (e)))
6133 		{
6134 		  uentry_showWhereAny (oe);
6135 		  uentry_setHasNameError (oe);
6136 		  gotone = TRUE;
6137 		}
6138 	    }
6139 	}
6140       else
6141 	{
6142 	  if (ignorecase)
6143 	    {
6144 	      if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6145 						   name, checklen))
6146 		{
6147 		  if (gotone)
6148 		    {
6149 		      extras = TRUE;
6150 		      break;
6151 		    }
6152 
6153 		  if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6154 		    {
6155 		      if (optgenerror
6156 			  (FLG_DISTINCTEXTERNALNAMES,
6157 			   /*@-sefparams@*/
6158 			   message
6159 			   ("External identifier %q is not distinguishable from %q "
6160 			    "in the first %d characters (%q)",
6161 			    uentry_getName (e),
6162 			    uentry_getName (oe),
6163 			    size_toInt (checklen),
6164 			    cstring_clip (uentry_getName (e), checklen)),
6165 			   /*@=sefparams@*/
6166 			   uentry_whereLast (e)))
6167 			{
6168 			  uentry_showWhereAny (oe);
6169 			  uentry_setHasNameError (oe);
6170 			  gotone = TRUE;
6171 			}
6172 		    }
6173 		  else
6174 		    {
6175 		      if (gotone)
6176 			{
6177 			  extras = TRUE;
6178 			  break;
6179 			}
6180 
6181 		      if (optgenerror
6182 			  (FLG_DISTINCTEXTERNALNAMES,
6183 			   message
6184 			   ("External identifier %q is not distinguishable from %q "
6185 			    "in the first %d characters because alphabetical case "
6186 			    "is ignored",
6187 			    uentry_getName (e),
6188 			    uentry_getName (oe),
6189 			    size_toInt (checklen)),
6190 			   uentry_whereLast (e)))
6191 			{
6192 			  uentry_showWhereAny (oe);
6193 			  uentry_setHasNameError (oe);
6194 			  gotone = TRUE;
6195 			}
6196 		    }
6197 		}
6198 	    }
6199 	  else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6200 	    {
6201 	      if (gotone)
6202 		{
6203 		  extras = TRUE;
6204 		  break;
6205 		}
6206 
6207 	      if (optgenerror
6208 		  (FLG_DISTINCTEXTERNALNAMES,
6209 		   /*@-sefparams@*/
6210 		   message
6211 		   ("External identifier %q is not distinguishable from %q "
6212 		    "in the first %d characters (%q)",
6213 		    uentry_getName (e),
6214 		    uentry_getName (oe),
6215 		    size_toInt (checklen),
6216 		    cstring_clip (uentry_getName (e), checklen)),
6217 		   /*@=sefparams@*/
6218 		   uentry_whereLast (e)))
6219 		{
6220 		  uentry_showWhereAny (oe);
6221 		  uentry_setHasNameError (oe);
6222 		  gotone = TRUE;
6223 		}
6224 	    }
6225 	  else
6226 	    {
6227 	      ; /* okay */
6228 	    }
6229 	}
6230     } end_usymtab_entries ;
6231 
6232   hasError = gotone;
6233 
6234   if (extras)
6235     {
6236       llgenindentmsgnoloc
6237 	(cstring_makeLiteral ("One or more additional "
6238 			      "indistinguishable external "
6239 			      "names not reported"));
6240     }
6241 
6242   return hasError;
6243 }
6244 
checkDistinctInternalName(uentry e)6245 static bool checkDistinctInternalName (uentry e)
6246   /*@globals utab@*/
6247   /*@modifies *g_warningstream@*/
6248 {
6249   usymtab ttab = utab;
6250   cstring name = uentry_rawName (e);
6251   size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6252   bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6253   bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6254 
6255   if (uentry_isAnyTag (e) && (numchars != 0))
6256     {
6257       numchars++;  /* the tag marker doesn't count */
6258     }
6259 
6260   while (usymtab_isDefined (ttab))
6261     {
6262       usymtab_entries (ttab, oe)
6263 	{
6264 	  if (uentry_sameObject (oe, e))
6265 	    {
6266 	      /*@innercontinue@*/ continue;
6267 	    }
6268 
6269 	  switch (cstring_genericEqual
6270 		  (name, uentry_rawName (oe),
6271 		   numchars, caseinsensitive, lookalike))
6272 	    {
6273 	    case CGE_DISTINCT: /* okay */
6274 	      /*@switchbreak@*/
6275 	      break;
6276 	    case CGE_SAME:
6277 	      if (cstring_equal (name, uentry_rawName (oe)))
6278 		{
6279 		  ; /* got a shadow error */
6280 		}
6281 	      else
6282 		{
6283 		  if (optgenerror
6284 		      (FLG_DISTINCTINTERNALNAMES,
6285 		       /*@-sefparams@*/
6286 		       message
6287 		       ("Internal identifier %q is not distinguishable from %q "
6288 			"in the first %d characters (%q)",
6289 			uentry_getName (e),
6290 			uentry_getName (oe),
6291 			size_toInt (numchars),
6292 			cstring_clip (uentry_getName (e), numchars)),
6293 		       /*@=sefparams@*/
6294 		       uentry_whereLast (e)))
6295 		    {
6296 		      uentry_showWhereAny (oe);
6297 		      uentry_setHasNameError (oe);
6298 		      return TRUE;
6299 		    }
6300 		}
6301 	      /*@switchbreak@*/
6302 	      break;
6303 	    case CGE_CASE:
6304 	      if (numchars == 0 || (cstring_length (name) <= numchars))
6305 		{
6306 		  if (optgenerror
6307 		      (FLG_DISTINCTINTERNALNAMES,
6308 		       message
6309 		       ("Internal identifier %q is not distinguishable from %q "
6310 			"without case sensitivity",
6311 			uentry_getName (e),
6312 			uentry_getName (oe)),
6313 		       uentry_whereLast (e)))
6314 		    {
6315 		      uentry_showWhereAny (oe);
6316 		      uentry_setHasNameError (oe);
6317 		      return TRUE;
6318 		    }
6319 		}
6320 	      else
6321 		{
6322 		  if (optgenerror
6323 		      (FLG_DISTINCTINTERNALNAMES,
6324 		       message
6325 		       ("Internal identifier %q is not distinguishable from %q "
6326 			"in the first %d characters without case sensitivity",
6327 			uentry_getName (e),
6328 			uentry_getName (oe),
6329 			size_toInt (numchars)),
6330 		       uentry_whereLast (e)))
6331 		    {
6332 		      uentry_showWhereAny (oe);
6333 		      uentry_setHasNameError (oe);
6334 		      return TRUE;
6335 		    }
6336 		}
6337 	      /*@switchbreak@*/
6338 	      break;
6339 	    case CGE_LOOKALIKE:
6340 	      if (numchars == 0
6341 		  || (cstring_length (name) <= numchars))
6342 		{
6343 		  if (optgenerror
6344 		      (FLG_DISTINCTINTERNALNAMES,
6345 		       message
6346 		       ("Internal identifier %q is not distinguishable from %q "
6347 			"except by lookalike characters",
6348 			uentry_getName (e),
6349 			uentry_getName (oe)),
6350 		       uentry_whereLast (e)))
6351 		    {
6352 		      uentry_showWhereAny (oe);
6353 		      uentry_setHasNameError (oe);
6354 		      return TRUE;
6355 		    }
6356 		}
6357 	      else
6358 		{
6359 		  if (optgenerror
6360 		      (FLG_DISTINCTINTERNALNAMES,
6361 		       message
6362 		       ("Internal identifier %q is not distinguishable from %q "
6363 			"in the first %d characters except by lookalike characters",
6364 			uentry_getName (e),
6365 			uentry_getName (oe),
6366 			size_toInt (numchars)),
6367 		       uentry_whereLast (e)))
6368 		    {
6369 		      uentry_showWhereAny (oe);
6370 		      uentry_setHasNameError (oe);
6371 		      return TRUE;
6372 		    }
6373 		}
6374 	    }
6375 	} end_usymtab_entries ;
6376 
6377       ttab = ttab->env;
6378     }
6379 
6380   return FALSE;
6381 }
6382 
usymtab_checkDistinctName(uentry e,int scope)6383 void usymtab_checkDistinctName (uentry e, int scope)
6384    /*@globals utab, globtab@*/
6385 {
6386   bool hasError = FALSE;
6387   fileloc where = uentry_whereLast (e);
6388 
6389   if (!fileloc_isPreproc (where)  && !fileloc_isBuiltin (where))
6390     {
6391       if (scope == globScope)
6392 	{
6393 	  if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6394 	    {
6395 	      hasError = checkDistinctExternalName (e);
6396 	    }
6397 	}
6398 
6399       if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6400 	{
6401 	  hasError = checkDistinctInternalName (e);
6402 	}
6403     }
6404 
6405   if (hasError)
6406     {
6407       uentry_setHasNameError (e);
6408     }
6409 }
6410 
usymtab_lookupGlobalMarker(void)6411 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6412 {
6413   uentry ue;
6414 
6415   ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6416   llassert (uentry_isValid (ue));
6417 
6418   return uentry_getSref (ue);
6419 }
6420 
6421 
6422 # ifdef DEBUGSPLINT
6423 /*
6424 ** For debugging only
6425 */
6426 
6427 void
usymtab_checkAllValid()6428 usymtab_checkAllValid () /*@globals utab@*/
6429 {
6430   usymtab tab = utab;
6431 
6432   while (tab != GLOBAL_ENV)
6433     {
6434       int i;
6435 
6436       for (i = 0; i < utab->nentries; i++)
6437 	{
6438 	  uentry e = utab->entries[i];
6439 
6440 	  uentry_checkValid (e);
6441 	}
6442 
6443       aliasTable_checkValid (tab->aliases);
6444       tab = tab->env;
6445     }
6446 }
6447 # endif
6448 
6449 
6450 
6451 
6452 
6453 
6454