]> andersk Git - splint.git/blame_incremental - src/usymtab.c
noexpand always false.
[splint.git] / src / usymtab.c
... / ...
CommitLineData
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
65static uentryList functypes = uentryList_undefined;
66
67static bool dbgfree = FALSE;
68static 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
77static 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
94static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
95
96/* Reachable environments from from utab */
97static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
98static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
99
100/* Used for sorting for dumpage. */
101static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
102
103static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
104static bool usymtab_isAltDefinitelyNull (sRef p_s) /*@globals utab@*/ ;
105static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
106static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
107
108static void usymtab_freeAux (/*@only@*/ usymtab p_u)
109 /*@globals globtab, utab, filetab@*/
110 /*@modifies p_u@*/ ;
111
112extern int usymtab_getCurrentDepth (void) /*@globals utab@*/
113{
114 return utab->lexlevel;
115}
116
117static void
118usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
119 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
120
121static bool usymtab_isDefinitelyNullAux (sRef p_s) /*@globals utab@*/ ;
122static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
123static /*@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... */
128static /*@unused@*/ /*@only@*/ cstring
129 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
130static /*@unused@*/ /*@only@*/ cstring
131 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
132# endif
133
134static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
135static void usymtab_handleParams (void)
136 /*@globals utab, globtab, filetab@*/
137 /*@modifies utab@*/ ;
138
139static /*@exposed@*/ /*@dependent@*/ uentry
140 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
141static /*@exposed@*/ /*@dependent@*/ usymtab
142 usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
143static /*@exposed@*/ /*@dependent@*/ uentry
144 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
145
146static /*@exposed@*/ /*@dependent@*/ uentry
147 usymtab_lookupQuietAux (usymtab p_s, cstring p_k, bool p_noalt);
148
149static /*@exposed@*/ /*@dependent@*/ uentry
150 usymtab_lookupQuiet (usymtab p_s, cstring p_k);
151
152static /*@exposed@*/ /*@dependent@*/ uentry
153 usymtab_lookupQuietNoAlt (usymtab p_s, cstring p_k);
154
155static 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
160static usymId usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
161static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, usymId p_ui);
162static /*@exposed@*/ uentry usymtab_lookupAux (usymtab p_s, cstring p_k);
163
164static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/
165 usymtab usymtab_getFileTab (void) /*@globals filetab@*/ ;
166
167static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, usymId p_index);
168static bool usymtab_mustBreak (usymtab p_s);
169static bool usymtab_mustEscape (usymtab p_s);
170
171static 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
181static 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
205static /*@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
212static bool usymtab_mustBreak (usymtab s)
213{
214 llassert (s != GLOBAL_ENV);
215 return (s->mustBreak);
216}
217
218static bool usymtab_mustEscape (usymtab s)
219{
220 llassert (s != GLOBAL_ENV);
221 return (exitkind_mustEscape (s->exitCode));
222}
223
224void usymtab_setMustBreak ()
225 /*@modifies utab@*/
226{
227 llassert (utab != GLOBAL_ENV);
228 utab->mustBreak = TRUE;
229}
230
231void 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
244bool usymtab_isAltDefinitelyNullDeep (sRef s)
245{
246 return (sRef_deepPred (usymtab_isAltDefinitelyNull, s));
247}
248
249static 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
280static /*@notnull@*/ /*@special@*/ usymtab
281 usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
282 /*@defines result@*/
283 /*@post:isnull result->htable, result->guards, result->aliases@*/
284{
285 usymtab t = (usymtab) dmalloc (sizeof (*t));
286
287 t->nentries = 0;
288 t->nspace = CBASESIZE;
289 t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
290
291 /* We only use a reftable for branch-level symbol tables.
292 */
293
294 t->reftable = (nextlevel
295 ? NULL
296 : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
297
298 t->kind = kind;
299 t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0);
300
301 t->env = env;
302 t->htable = NULL;
303
304 t->guards = guardSet_undefined;
305 t->aliases = aliasTable_undefined;
306
307 t->mustBreak = FALSE;
308 t->exitCode = XK_NEVERESCAPE;
309
310 DPRINTF (("Create usymtab [%p]", t));
311 return t;
312}
313
314/*
315** constructors
316*/
317
318static /*@only@*/ /*@notnull@*/ usymtab
319 usymtab_createRoot (void) /*@modifies nothing@*/
320{
321 usymtab u = (usymtab) dmalloc (sizeof (*u));
322
323 u->nentries = 0;
324 u->nspace = CGLOBBASESIZE;
325 u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
326 u->env = GLOBAL_ENV;
327 u->lexlevel = 0;
328 u->htable = cstringTable_create (CGLOBHASHSIZE);
329 u->reftable = NULL;
330
331 u->guards = guardSet_new ();
332 u->aliases = aliasTable_new ();
333
334 u->mustBreak = FALSE;
335 u->exitCode = XK_NEVERESCAPE;
336 u->kind = US_NORMAL;
337
338 return (u);
339}
340
341void
342usymtab_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
352void
353usymtab_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
361void
362usymtab_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
381void
382usymtab_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
416static void
417usymtab_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
452static void
453usymtab_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
513static /*@observer@*/ uentry /*@alt void@*/
514usymtab_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
549static /*@observer@*/ uentry /*@alt void@*/
550usymtab_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
588static usymId
589usymtab_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
684usymId
685usymtab_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
695void
696usymtab_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
712static usymId
713usymtab_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
1046static void
1047usymtab_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
1077void 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
1088static /*@exposed@*/ uentry
1089 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1090 /*@only@*/ uentry e, bool isref)
1091 /*@globals globtab, filetab@*/
1092 /*@modifies tab, globtab, e@*/
1093{
1094 cstring rawName = cstring_copy (uentry_rawName (e));
1095 bool stat = (tab == globtab) && uentry_isStatic (e);
1096 uentry ret;
1097
1098 (void) usymtab_supEntryAux (tab, e, isref);
1099
1100 if (stat)
1101 {
1102 ret = usymtab_lookupAux (filetab, rawName);
1103 }
1104 else
1105 {
1106 ret = usymtab_lookupAux (tab, rawName);
1107
1108 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1109 {
1110 ret = usymtab_lookupAux (filetab, rawName);
1111 }
1112 }
1113
1114 cstring_free (rawName);
1115 return ret;
1116}
1117
1118/*@dependent@*/ /*@exposed@*/ uentry
1119 usymtab_supEntryReturn (/*@only@*/ uentry e)
1120 /*@globals utab, filetab, globtab@*/
1121 /*@modifies utab, globtab, e@*/
1122{
1123 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1124}
1125
1126/*@dependent@*/ /*@exposed@*/ uentry
1127 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1128 /*@globals utab, globtab, filetab@*/
1129 /*@modifies utab, globtab, e@*/
1130{
1131 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1132}
1133
1134/*@dependent@*/ /*@exposed@*/ uentry
1135 usymtab_supGlobalEntryReturn (uentry e)
1136 /*@globals globtab, filetab@*/
1137 /*@modifies globtab, e@*/
1138{
1139 uentry ret;
1140
1141 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1142
1143 /*
1144 ** We need to keep track of internal function declarations, so
1145 ** we can remove them from the symbol table after exiting this
1146 ** function. This is a bit bogus, of course.
1147 */
1148
1149 if (sRef_modInFunction ())
1150 {
1151 recordFunctionType (ret);
1152 }
1153
1154 return (ret);
1155}
1156
1157ctype
1158usymtab_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
1185uentry
1186usymtab_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
1266typeId
1267usymtab_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
1295typeId
1296usymtab_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
1319ctype
1320usymtab_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
1337void
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
1368void 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
1384uentry
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
1398bool
1399usymtab_inDeepScope () /*@globals utab@*/
1400{
1401 return (utab->lexlevel > paramsScope);
1402}
1403
1404static usymId
1405usymtab_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
1435static uentry
1436usymtab_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
1443typeId
1444usymtab_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
1461usymtab_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
1471usymtab_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
1481usymtab_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
1490usymId
1491usymtab_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
1511static /*@exposed@*/ uentry
1512usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1513{
1514 llassert (uid != usymId_invalid);
1515
1516 if (uid < 0 || uid >= usymId_fromInt (s->nentries))
1517 {
1518 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1519 s->lexlevel, uid));
1520 return uentry_undefined;
1521 }
1522
1523 llassertprint (uentry_isValid (s->entries[uid]),
1524 ("entry undefined: %d", uid));
1525
1526 return s->entries[uid];
1527}
1528
1529/*@dependent@*/ /*@observer@*/ uentry
1530 usymtab_getGlobalEntry (usymId uid)
1531 /*@globals utab, globtab@*/
1532{
1533 if (dbgfree) return (uentry_undefined);
1534
1535 if (utab->lexlevel > paramsScope)
1536 {
1537 /* need to do this the awkward way, since it could be in conditional scope */
1538 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1539 }
1540 else
1541 {
1542 return (globtab->entries[uid]);
1543 }
1544}
1545
1546/*@dependent@*/ /*@exposed@*/ uentry usymtab_getTypeEntry (typeId uid)
1547 /*@globals globtab@*/
1548{
1549 if (dbgload)
1550 {
1551 if (uid >= 0 && uid < typeId_fromInt (globtab->nentries))
1552 {
1553 return (globtab->entries[uid]);
1554 }
1555 else
1556 {
1557 return (uentry_undefined);
1558 }
1559 }
1560 else
1561 {
1562 llassert (uid >= 0 && uid < typeId_fromInt (globtab->nentries));
1563 return (globtab->entries[uid]);
1564 }
1565}
1566
1567/*
1568** in load files
1569*/
1570
1571/*@dependent@*/ /*@exposed@*/ uentry usymtab_getTypeEntrySafe (typeId uid)
1572 /*@globals globtab@*/
1573{
1574 if (uid < 0 || uid >= typeId_fromInt (globtab->nentries))
1575 {
1576 return uentry_undefined;
1577 }
1578
1579 return (globtab->entries[uid]);
1580}
1581
1582bool 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
1591cstring 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
1615usymtab_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
1639static /*@only@*/ /*@notnull@*/ usymtab
1640usymtab_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
1653static void
1654usymtab_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
1662usymId 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
1671usymId 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
1697void
1698usymtab_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
1731void 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
1888void 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 llbuglit ("Junk in load file");
2013 s++;
2014 }
2015
2016 nextiter:
2017 {
2018 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
2019 }
2020 }
2021
2022 /*DRL added 6/21/01
2023 to handle reading of buffer overflow related constraints
2024 */
2025 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
2026 && *s == ';')
2027 {
2028 ; /* ignore ;-comments */
2029 }
2030
2031 /*drl July 27 added this so that libraries without
2032 buffer constraints would be handled correctly.
2033 I'm trying to do this without breaking older libraries*/
2034
2035 /*check for "optional" start buffer constraints message*/
2036
2037 if (mstring_equalPrefix (s, "start_Buffer_Constraints"))
2038 {
2039 (void) fgets (s, MAX_DUMP_LINE_LENGTH, f);
2040 }
2041
2042 while (s != NULL && *s != ';')
2043 {
2044 constraintList preconditions;
2045 constraintList postconditions;
2046 cstring name = cstring_fromChars (reader_getWord (&s));
2047 cstring temp;
2048
2049 ue = usymtab_lookup (name);
2050 cstring_free (name);
2051
2052 preconditions = constraintList_undefined;
2053 postconditions = constraintList_undefined;
2054
2055 if (!uentry_isValid(ue) )
2056 {
2057 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2058 }
2059 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2060
2061 temp = cstring_fromChars (reader_getWord(&s) );
2062
2063 if (cstring_compareLit (temp,"pre:") == 0 )
2064 {
2065 preconditions = constraintList_undump (f);
2066 }
2067 else
2068 {
2069 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2070 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2071 }
2072
2073 cstring_free(temp);
2074
2075 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2076
2077 temp = cstring_fromChars(reader_getWord(&s) );
2078 if (cstring_compareLit (temp, "post:") == 0 )
2079 {
2080 postconditions = constraintList_undump (f);
2081 }
2082 else
2083 {
2084 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2085 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2086 }
2087
2088 cstring_free (temp);
2089
2090 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2091 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2092
2093 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2094 }
2095
2096 dbgload = FALSE;
2097 sfree (os);
2098}
2099
2100/*
2101** file scope for static variables
2102*/
2103
2104void
2105usymtab_enterFile ()
2106 /*@globals utab, globtab, filetab@*/
2107 /*@modifies filetab@*/
2108{
2109 llassert (utab == globtab);
2110
2111 # if 0
2112 /* check globals */
2113
2114 usymtab_entries (globtab, ue)
2115 {
2116 if (sRef_hasDerived (uentry_getSref (ue)))
2117 {
2118 fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2119 fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2120 }
2121 } end_usymtab_entries ;
2122
2123 # endif
2124
2125 usymtab_enterScope ();
2126 filetab = utab;
2127}
2128
2129void
2130usymtab_exitFile ()
2131 /*@globals utab, filetab@*/
2132 /*@modifies filetab, utab@*/
2133{
2134
2135 llassert (utab->lexlevel == 1);
2136
2137 usymtab_exitScope (exprNode_undefined);
2138 filetab = NULL;
2139}
2140
2141void
2142usymtab_enterScope ()
2143 /*@globals utab, globtab, filetab@*/
2144 /*@modifies utab@*/
2145{
2146 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2147
2148 /* unconditional scope: optimize to avoid copy */
2149 t->aliases = aliasTable_copy (utab->aliases);
2150 utab = t;
2151
2152 llassert (usymtab_isDefined (t->env));
2153
2154 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2155 {
2156 noshadowerror = TRUE;
2157 usymtab_handleParams ();
2158 noshadowerror = FALSE;
2159 }
2160}
2161
2162/*
2163** setup external references:
2164** o only, unique params alias external args
2165** o other params may alias anything of their type
2166*/
2167
2168static void
2169usymtab_handleParams (void)
2170 /*@globals utab, globtab, filetab@*/
2171 /*@modifies utab, globtab@*/
2172{
2173 usymtab ptab = utab->env;
2174 uentry fcn = context_getHeader ();
2175
2176 usymtab_entries (ptab, param)
2177 {
2178 uentry ue;
2179
2180 if (!uentry_isYield (param))
2181 {
2182 sRef uref;
2183 sRef pref = uentry_getSref (param);
2184
2185 /* Could be a global. */
2186
2187 if (uentry_isAnyParam (param))
2188 {
2189 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2190 uentry_getType (param),
2191 fileloc_copy (uentry_whereDeclared (param)),
2192 FALSE);
2193
2194 uentry_copyState (ue, param);
2195 uentry_setRefParam (ue);
2196
2197 ue = usymtab_supEntrySrefReturn (ue);
2198
2199 /* must be after supercede! */
2200
2201 if (!sRef_stateKnown (pref))
2202 {
2203 uentry_setDefState (ue, SS_DEFINED);
2204 uentry_setDefState (param, SS_DEFINED);
2205 }
2206 else
2207 {
2208 if (sRef_isStateSpecial (pref))
2209 {
2210 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2211 /* evans 2002-01-01: should be unnecessary, the pre clauses
2212 ** set the state if necessary.
2213 */
2214 }
2215 else
2216 {
2217 uentry_setDefState (ue, sRef_getDefState (pref));
2218 }
2219 }
2220
2221 uref = uentry_getSref (ue);
2222
2223 if (sRef_isStack (uref))
2224 {
2225 alkind pkind = sRef_getAliasKind (pref);
2226
2227 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2228 && !alkind_isStack (pkind))
2229 {
2230 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2231 sRef_setOrigAliasKind (uref, pkind);
2232 }
2233 else
2234 {
2235 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2236 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2237
2238 if (uentry_isOut (param))
2239 {
2240 ;
2241 }
2242 else
2243 {
2244 sRef_setDefined (uref, fileloc_undefined);
2245 }
2246 }
2247
2248 }
2249
2250 usymtab_addMustAlias (uref, pref);
2251
2252 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2253 {
2254 /*
2255 ** This is needed for detecting possibly aliased parameters.
2256 */
2257
2258 sRef s = sRef_makeExternal (uref);
2259 usymtab_addMustAlias (uref, s);
2260 }
2261
2262 if (sRef_isKillRef (pref))
2263 {
2264 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2265 sRef_setOrigAliasKind (uref, AK_KILLREF);
2266 }
2267 else if (sRef_isRefCounted (uref))
2268 {
2269 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2270 }
2271 else
2272 {
2273 /* was AK_UNIQUE */
2274 sRef_setOrigAliasKind (uref, AK_LOCAL);
2275 }
2276 }
2277 else
2278 {
2279 }
2280 }
2281 } end_usymtab_entries;
2282
2283
2284 if (uentry_hasStateClauseList (fcn))
2285 {
2286 stateClauseList clauses = uentry_getStateClauseList (fcn);
2287
2288 stateClauseList_preElements (clauses, cl)
2289 {
2290 fileloc loc = stateClause_loc (cl);
2291 sRefSet osrs = sRefSet_undefined;
2292 sRefSet srs;
2293
2294 if (stateClause_isGlobal (cl))
2295 {
2296 DPRINTF (("Global Marker: %s",
2297 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2298 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2299 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2300 osrs = srs;
2301 }
2302 else
2303 {
2304 srs = stateClause_getRefs (cl);
2305 }
2306
2307 sRefSet_elements (srs, el)
2308 {
2309 sRef base = sRef_getRootBase (el);
2310 sRef sb = sRef_updateSref (el);
2311
2312 if (sRef_isResult (base))
2313 {
2314 ; /* nothing to do before */
2315 }
2316 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2317 {
2318 if (stateClause_setsMetaState (cl))
2319 {
2320 /* copied from exprNode.c:3040 */
2321 qual ql = stateClause_getMetaQual (cl);
2322 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2323 metaStateInfo minfo = annotationInfo_getState (ainfo);
2324 cstring key = metaStateInfo_getName (minfo);
2325 int mvalue = annotationInfo_getValue (ainfo);
2326
2327 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2328
2329 if (sRef_isResult (base))
2330 {
2331 BADBRANCH;
2332 }
2333 else
2334 {
2335 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2336 }
2337 }
2338 else
2339 {
2340 sRefMod modf = stateClause_getEntryFunction (cl);
2341
2342 if (modf != NULL)
2343 {
2344 sRefSet aliases = usymtab_allAliases (sb);
2345
2346 modf (sb, loc);
2347
2348 sRefSet_elements (aliases, sr)
2349 {
2350 modf (sr, loc);
2351 } end_sRefSet_elements ;
2352
2353 sRefSet_free (aliases);
2354 }
2355 }
2356 }
2357 else
2358 {
2359 if (sRef_isValid (base))
2360 {
2361 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2362 BADBRANCH;
2363 }
2364 }
2365 } end_sRefSet_elements ;
2366 } end_stateClauseList_preElements ;
2367 }
2368}
2369
2370void
2371usymtab_enterFunctionScope (uentry fcn)
2372 /*@globals utab, filetab, globtab@*/
2373 /*@modifies utab@*/
2374{
2375 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2376
2377 DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2378
2379 if (utab->lexlevel != fileScope)
2380 {
2381 if (utab->lexlevel > fileScope)
2382 {
2383 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2384
2385 while (utab->lexlevel > fileScope)
2386 {
2387 /*@i@*/ utab = usymtab_dropEnv (utab);
2388 /*@-branchstate@*/
2389 }
2390 /*@=branchstate@*/
2391 }
2392 else
2393 {
2394 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2395 }
2396 /*@-branchstate@*/ } /*@=branchstate@*/
2397
2398 utab = t;
2399
2400 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2401
2402 globSet_allElements (uentry_getGlobs (fcn), el)
2403 {
2404 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2405
2406 if (sRef_isUndefGlob (el))
2407 {
2408 usymId index = sRef_getScopeIndex (el);
2409 sRef sr = sRef_updateSref (el);
2410 fileloc loc = uentry_whereEarliest (fcn);
2411
2412 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2413 DPRINTF (("Undef!"));
2414 if (sRef_isFileStatic (el))
2415 {
2416 ctype ct = sRef_getType (el);
2417 uentry ue;
2418
2419 llassert (usymtab_isDefined (filetab));
2420
2421 ue = usymtab_fetchIndex (filetab, index);
2422
2423 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2424 {
2425 sRef_setAllocated (sr, loc);
2426 }
2427 else
2428 {
2429 sRef_setUndefined (sr, loc);
2430 }
2431 }
2432 else
2433 {
2434 uentry ue = globtab->entries[index];
2435 ctype ct = uentry_getType (ue);
2436
2437 if (ctype_isArray (ct) || ctype_isSU (ct))
2438 {
2439 sRef_setAllocated (sr, loc);
2440 }
2441 else
2442 {
2443 sRef_setUndefined (sr, loc);
2444 }
2445 }
2446 }
2447 else if (sRef_isAllocated (el))
2448 {
2449 sRef sr = sRef_updateSref (el);
2450 fileloc loc = uentry_whereEarliest (fcn);
2451
2452 sRef_setAllocated (sr, loc);
2453 }
2454 else if (sRef_isPartial (el))
2455 {
2456 sRef sr = sRef_updateSref (el);
2457 fileloc loc = uentry_whereEarliest (fcn);
2458
2459 sRef_setPartial (sr, loc);
2460 }
2461 else
2462 {
2463 /*
2464 sRef sr = sRef_updateSref (el);
2465 fileloc loc = uentry_whereEarliest (fcn);
2466
2467 sRef_setDefined (sr, loc);
2468 */
2469
2470 /* defined */
2471 /* shouldn't need to do anything! */
2472 }
2473 } end_globSet_allElements;
2474
2475 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2476# ifdef DEBUGSPLINT
2477 usymtab_checkAllValid ();
2478# endif
2479}
2480
2481static void
2482usymtab_caseBranch (void)
2483 /*@modifies utab@*/
2484{
2485 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2486 utab = t;
2487}
2488
2489void
2490usymtab_switchBranch (/*@unused@*/ exprNode s)
2491 /*@modifies utab@*/
2492{
2493 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2494
2495 t->aliases = aliasTable_copy (utab->aliases);
2496 utab = t;
2497}
2498
2499void
2500usymtab_trueBranch (/*@only@*/ guardSet guards)
2501 /*@modifies utab@*/
2502{
2503 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2504
2505 /*
2506 ** not true! (could be in a macro)
2507 **
2508 ** llassertprint (utab->lexlevel > paramsScope,
2509 ** ("not in scope: %s", usymtab_unparseLocal ()));
2510 **
2511 */
2512
2513 guardSet_free (t->guards);
2514 t->guards = guards;
2515
2516 aliasTable_free (t->aliases);
2517 t->aliases = aliasTable_copy (utab->aliases);
2518
2519 utab = t;
2520}
2521
2522/*
2523** consider,
2524**
2525** { int a; if (...) a = 3; < a may be undefined here!
2526**
2527*/
2528
2529void
2530usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2531{
2532 /*
2533 ** add a false branch
2534 ** (could be done more efficiently as a special case, but
2535 ** it is better to only maintain one version of the code)
2536 */
2537
2538 if (utab->kind != US_TBRANCH
2539 && context_inIterDef ())
2540 {
2541 usymtab_exitScope (expr);
2542 }
2543 else
2544 {
2545 DPRINTF (("pop true branch.."));
2546 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2547 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2548 }
2549}
2550
2551void
2552usymtab_popCaseBranch () /*@modifies utab@*/
2553{
2554 llassert (utab->kind == US_CBRANCH);
2555 usymtab_quietPlainExitScope ();
2556}
2557
2558void
2559usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2560{
2561 /*
2562 ** add a false branch that must return --- that is,
2563 ** the true branch is always executed!
2564 */
2565
2566 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2567 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2568}
2569
2570void
2571usymtab_popOrBranch (exprNode pred, exprNode expr)
2572 /*@modifies utab@*/
2573{
2574 bool mustReturn;
2575 usymtab env = utab->env;
2576 usymtab otab = utab;
2577 int i = 0;
2578
2579 llassert (env != NULL);
2580
2581 if (exprNode_isError (expr))
2582 {
2583 mustReturn = FALSE;
2584 }
2585 else
2586 {
2587 mustReturn = exprNode_mustEscape (expr);
2588 }
2589
2590
2591 llassert (utab->kind == US_TBRANCH);
2592
2593 /*
2594 ** merge each entry in table with its original
2595 ** unless execution cannot continue after this branch
2596 */
2597
2598 for (i = 0; i < utab->nentries; i++)
2599 {
2600 uentry current = utab->entries[i];
2601 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2602
2603 uentry_mergeState (old, current, exprNode_loc (expr),
2604 mustReturn, FALSE, TRUE, ORCLAUSE);
2605 }
2606
2607
2608 if (mustReturn)
2609 {
2610 env->guards = guardSet_levelUnionFree (env->guards,
2611 guardSet_invert (exprNode_getGuards (pred)),
2612 env->lexlevel);
2613 }
2614 else
2615 {
2616 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2617 }
2618
2619 /* env is now utab */
2620 usymtab_quietPlainExitScope ();
2621}
2622
2623/*
2624** case syntax in C is very unrestricted. This is unfortunate.
2625**
2626** A switch case is ended either by a new case or default, or
2627** a close } that may close the switch or some other control
2628** structure.
2629*/
2630
2631bool
2632usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2633 /*@modifies utab@*/
2634{
2635 bool mustBreak = usymtab_mustBreak (utab);
2636 bool mustReturn = usymtab_mustEscape (utab);
2637 usymtab stab = utab;
2638
2639 DPRINTF (("New case!"));
2640
2641 /*
2642 ** Find last case (or outer switch)
2643 */
2644
2645 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2646 {
2647 stab = stab->env;
2648 llassert (stab != GLOBAL_ENV);
2649 }
2650
2651 while (stab->kind == US_CBRANCH)
2652 {
2653 stab = stab->env;
2654 llassert (stab != GLOBAL_ENV);
2655 }
2656
2657 /*
2658 ** if its a fall through case, merge in outside entries and last case.
2659 **
2660 ** e.g.,
2661 ** ...
2662 ** switch
2663 ** case 1: x = 3; <fall through>
2664 ** case 2: << x may not be defined
2665 **
2666 */
2667
2668 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2669 {
2670 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2671
2672 usymtab_entries (utab, ue) /* but, keep track of used variables */
2673 {
2674 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2675
2676 llassert (uentry_isValid (old));
2677
2678 /* modifies ue, not old */
2679
2680 uentry_mergeState (ue, old, exprNode_loc (last),
2681 FALSE, FALSE, TRUE, CASECLAUSE);
2682 } end_usymtab_entries;
2683
2684 utab->aliases = aliasTable_levelUnion (utab->aliases,
2685 stab->aliases, utab->lexlevel);
2686
2687 /*
2688 ** No need for a new branch.
2689 */
2690
2691 return FALSE;
2692 }
2693 else
2694 {
2695 usymtab_caseBranch ();
2696 /*@-mustfree@*/ /*< utab->aliases >*/
2697 utab->aliases = aliasTable_copy (stab->aliases);
2698 /*@=mustfree@*/
2699
2700 return TRUE;
2701 }
2702}
2703
2704/*
2705** for && (both pred and expr are executed)
2706*/
2707
2708void
2709usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2710 /*@modifies utab@*/
2711{
2712 usymtab env = utab->env;
2713 usymtab otab= utab;
2714 int i = 0;
2715
2716 llassert (utab->kind == US_TBRANCH);
2717
2718 /*
2719 ** merge each entry in table with its original
2720 ** unless execution cannot continue after this branch
2721 */
2722
2723 for (i = 0; i < utab->nentries; i++)
2724 {
2725 uentry current = utab->entries[i];
2726 sRef tref = uentry_getSref (current);
2727 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2728 sRef oref = uentry_getSref (old);
2729
2730 /* note that is current is in a nested branch,
2731 it may create a "new" old entry. */
2732
2733 llassert (uentry_isValid (old));
2734 uentry_mergeState (old, current, exprNode_loc (expr),
2735 FALSE, FALSE, TRUE, ANDCLAUSE);
2736
2737 /*
2738 ** if is it defined by the second clause, then it should be defined.
2739 */
2740
2741 if (sRef_isAnyDefined (tref)
2742 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2743 {
2744 sRef_setDefined (oref, g_currentloc);
2745 }
2746 }
2747
2748 DPRINTF (("Popping and: %s / %s",
2749 guardSet_unparse (utab->guards),
2750 guardSet_unparse (exprNode_getGuards (pred))));
2751
2752 utab->guards = guardSet_levelUnionFree (utab->guards,
2753 guardSet_invert (exprNode_getGuards (pred)),
2754 utab->lexlevel);
2755 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2756
2757 usymtab_quietPlainExitScope ();
2758
2759 }
2760
2761/*
2762** Stack should be [ US_CBRANCH+ US_SWITCH ]
2763** Only branches which do not return (except possibly the last branch) are included.
2764**
2765** Conditionally merge state from all CBRANCHes.
2766**
2767** If allpaths is TRUE, then all possible executions go through some switch
2768** case, and the original scope is not merged.
2769*/
2770
2771void
2772usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2773 /*@modifies utab@*/
2774{
2775 usymtab ttab = utab;
2776 usymtab stab = ttab;
2777 usymtab ltab = ttab;
2778 bool lastMustReturn = usymtab_mustEscape (utab);
2779 int i;
2780
2781
2782 while (stab->kind == US_CBRANCH)
2783 {
2784 stab = stab->env;
2785 llassert (stab != GLOBAL_ENV);
2786 }
2787
2788 while (stab->kind == US_NORMAL)
2789 {
2790 stab = stab->env;
2791 llassert (stab != GLOBAL_ENV);
2792 }
2793
2794 llassert (stab->kind == US_SWITCH);
2795
2796 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2797 stab = stab->env;
2798 llassert (stab != GLOBAL_ENV);
2799
2800
2801 ttab = ttab->env;
2802 llassert (usymtab_isDefined (ttab));
2803
2804 if (ttab->kind == US_CBRANCH)
2805 {
2806 /* was quietPlainExitScope --- but, can't free it yet! */
2807 utab = utab->env;
2808 llassert (utab != GLOBAL_ENV);
2809
2810 while (ttab->kind == US_CBRANCH)
2811 {
2812 /*
2813 ** (from popTrueBranch)
2814 */
2815
2816 bool mustReturn = usymtab_mustEscape (ttab);
2817 bool mustBreak = usymtab_mustBreak (ttab);
2818
2819 usymtab_entries (ttab, current)
2820 {
2821 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2822 /*@=compmempass@*/
2823
2824 /*
2825 ** note that is this is in a nested branch,
2826 ** it may create a "new" old entry.
2827 */
2828
2829 if (uentry_isValid (old))
2830 {
2831 if (lastMustReturn)
2832 {
2833 uentry_mergeUses (current, old);
2834 uentry_setState (old, current);
2835 }
2836 else
2837 {
2838 uentry_mergeState (old, current, exprNode_loc (sw),
2839 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2840 }
2841 }
2842 else
2843 {
2844 ;
2845 }
2846 } end_usymtab_entries;
2847
2848 /*
2849 ** if entry is not in symbol table for this case, merge with pre-switch
2850 ** table
2851 */
2852
2853 if (!mustReturn && !mustBreak)
2854 {
2855 usymtab_entries (stab, current)
2856 {
2857 if (!usymtab_indexFound (usymtab_getIndex (ttab, uentry_rawName (current))))
2858 {
2859 uentry old = /*@-compmempass@*/
2860 usymtab_lookupAux (ltab, uentry_rawName (current));
2861 /*@=compmempass@*/
2862
2863 llassert (uentry_isValid (old));
2864 uentry_mergeState (old, current, exprNode_loc (sw),
2865 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2866 }
2867 } end_usymtab_entries;
2868 }
2869
2870 ltab->env = ttab->env;
2871 ttab = ltab->env;
2872
2873 /*
2874 ** Suprious error, becuase of environments.
2875 */
2876
2877 /*@i1@*/ utab = ltab;
2878
2879 lastMustReturn = FALSE;
2880 /*@-branchstate@*/
2881 }
2882 }
2883 /*@=branchstate@*/
2884
2885 /*
2886 ** now, there is one US_CBRANCH. Merge this with the stab.
2887 */
2888
2889
2890 for (i = 0; i < ltab->nentries; i++)
2891 {
2892 uentry current = ltab->entries[i];
2893 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2894
2895 /* note that is this is in a nested branch,
2896 it may create a "new" old entry. */
2897
2898
2899 if (uentry_isValid (old))
2900 {
2901 if (allpaths)
2902 {
2903 uentry_mergeUses (current, old);
2904 uentry_setState (old, current);
2905 }
2906 else
2907 {
2908 uentry_mergeState (old, current, exprNode_loc (sw),
2909 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2910 }
2911 }
2912 else
2913 {
2914 }
2915 }
2916
2917 /*
2918 ** exit the switch
2919 */
2920
2921
2922 /*
2923 ** switch may or may not be followed by a new scope
2924 */
2925
2926 if (utab->kind == US_SWITCH)
2927 {
2928 usymtab_quietPlainExitScope ();
2929 }
2930 else
2931 {
2932 usymtab_quietPlainExitScope ();
2933 llassert (utab->kind == US_SWITCH);
2934 usymtab_quietPlainExitScope ();
2935 }
2936
2937 }
2938
2939static void
2940updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2941 /*@notnull@*/ usymtab ftab, bool trueGuard)
2942{
2943 sRef base = sRef_getRootBase (el);
2944 int level = sRef_lexLevel (base);
2945
2946 if (sRef_isCvar (base))
2947 {
2948 usymId index = sRef_getScopeIndex (base);
2949 uentry ue = usymtab_getRefTab (ttab, level, index);
2950
2951 if (!uentry_isLset (ue))
2952 {
2953 sRef sr = uentry_getSref (ue);
2954
2955 if (trueGuard)
2956 {
2957 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2958 }
2959 else
2960 {
2961 if (!guardSet_isGuarded (ttab->guards, el)
2962 && !sRef_isNotNull (sr))
2963 {
2964 DPRINTF (("Here! %s / %s",
2965 sRef_unparseFull (sr),
2966 sRef_unparseFull (el)));
2967 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2968 }
2969 }
2970 }
2971 else
2972 {
2973 ;
2974 }
2975
2976 ue = usymtab_getRefTab (ftab, level, index);
2977
2978 if (!uentry_isLset (ue))
2979 {
2980 sRef sr = uentry_getSref (ue);
2981
2982 if (!trueGuard) /* yikes! forgot the ! */
2983 {
2984 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2985 }
2986 else
2987 {
2988
2989 if (!guardSet_isGuarded (ftab->guards, el)
2990 && !sRef_isNotNull (sr))
2991 {
2992 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2993 }
2994 }
2995 }
2996 else
2997 {
2998 ;
2999 }
3000 }
3001}
3002
3003void
3004usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
3005 bool isOpt, clause cl)
3006 /*@modifies utab@*/
3007{
3008 int i = 0;
3009 usymtab ftab = utab;
3010 usymtab ttab = utab->env;
3011
3012 fileloc loc;
3013 usymtab env;
3014 guardSet guards = exprNode_getGuards (pred);
3015 sRefSet tguards = guardSet_getTrueGuards (guards);
3016 sRefSet fguards = guardSet_getFalseGuards (guards);
3017 bool mustReturnT = exprNode_mustEscape (tbranch);
3018 bool mustReturnF = exprNode_mustEscape (fbranch);
3019
3020 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
3021 bool_unparse (mustReturnT),
3022 bool_unparse (mustReturnF)));
3023
3024 if (exprNode_isDefined (fbranch))
3025 {
3026 loc = exprNode_loc (fbranch);
3027 }
3028 else
3029 {
3030 loc = exprNode_loc (tbranch);
3031 }
3032
3033 llassert (usymtab_isDefined (ttab));
3034
3035 env = ttab->env;
3036
3037 llassert (usymtab_isDefined (env));
3038 llassert (ftab->kind == US_FBRANCH);
3039 llassert (ttab->kind == US_TBRANCH);
3040
3041 /*
3042 ** For each element that is true guarded (i.e., if (x != NULL))
3043 ** make x = null in false branch,
3044 ** and x = notnull in true branch.
3045 ** unless x was set locally in that branch.
3046 ** For each element that is false guarded (x == NULL)
3047 ** make x = null in true, notnull in false.
3048 **
3049 ** For each element that is either guarded (pred(x))
3050 **
3051 */
3052
3053 sRefSet_allElements (tguards, el)
3054 {
3055 updateNullState (el, ttab, ftab, TRUE);
3056 } end_sRefSet_allElements;
3057
3058 sRefSet_allElements (fguards, el)
3059 {
3060 updateNullState (el, ttab, ftab, FALSE);
3061 } end_sRefSet_allElements;
3062
3063 /*
3064 **
3065 ** if an entry is in both true and false, merge the entries,
3066 ** then replace original with new state.
3067 **
3068 ** if an entry is in one table, merge it with the original.
3069 */
3070
3071 DPRINTF (("ftab: %d", ftab->nentries));
3072
3073 for (i = 0; i < ftab->nentries; i++)
3074 {
3075 uentry fthis = ftab->entries[i];
3076 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3077 usymId tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3078
3079 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3080
3081 if (uentry_isUndefined (old))
3082 {
3083 /* possible entry was added as an undefined id */
3084 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3085 continue;
3086 }
3087
3088 if (usymtab_indexFound (tindex))
3089 {
3090 uentry tthis = ttab->entries[tindex];
3091
3092 /* note that is this is in a nested branch,
3093 it may create a "new" old entry. */
3094
3095 if (!mustReturnF)
3096 {
3097 if (!mustReturnT)
3098 {
3099 uentry_mergeState (fthis, tthis, loc,
3100 mustReturnT, FALSE, FALSE, cl);
3101 }
3102 else
3103 {
3104 uentry_mergeUses (fthis, tthis);
3105 }
3106
3107 uentry_setState (old, fthis);
3108
3109 /*@-mustfree@*/
3110 }
3111 /*@=mustfree@*/
3112 else
3113 {
3114 uentry_setState (old, tthis);
3115 uentry_mergeState (old, fthis, loc, mustReturnF,
3116 TRUE, FALSE, cl);
3117 }
3118
3119 ttab->entries[tindex] = uentry_undefined;
3120 uentry_free (tthis);
3121 }
3122 else
3123 {
3124 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3125 }
3126 }
3127
3128 for (i = 0; i < ttab->nentries; i++)
3129 {
3130 uentry current = ttab->entries[i];
3131
3132 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3133
3134 if (!uentry_isUndefined (current))
3135 {
3136 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3137
3138 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3139
3140 if (uentry_isUndefined (old))
3141 {
3142 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3143 continue;
3144 }
3145
3146 if (mustReturnF)
3147 {
3148 uentry_mergeUses (current, old);
3149 uentry_setState (old, current);
3150 }
3151 else
3152 {
3153 /*
3154 ** Assumes false branch is a fall-through if
3155 ** fbranch is not defined. This is true, unless
3156 ** where was some greivous error in processing
3157 ** the else branch of an if-then, in which case
3158 ** this is probably the right thing to do anyway.
3159 */
3160
3161 uentry_mergeState (old, current, loc, mustReturnT,
3162 FALSE, isOpt, cl);
3163 }
3164
3165 DPRINTF (("==> %s", uentry_unparseFull (old)));
3166 }
3167 }
3168
3169 /*
3170 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3171 ** if they are present.
3172 */
3173
3174 llassert (NOALIAS (env->aliases, ttab->aliases));
3175 llassert (NOALIAS (env->aliases, ftab->aliases));
3176
3177 aliasTable_free (env->aliases);
3178
3179 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3180 ftab->aliases, env->lexlevel);
3181
3182 aliasTable_fixSrefs (env->aliases);
3183
3184 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3185
3186 /* exit true and false scopes */
3187 usymtab_quietPlainExitScope ();
3188 usymtab_quietPlainExitScope ();
3189
3190 if (mustReturnT)
3191 {
3192 utab->guards = guardSet_levelUnionFree
3193 (utab->guards,
3194 guardSet_invert (exprNode_getGuards (pred)),
3195 utab->lexlevel);
3196 }
3197
3198 if (mustReturnF)
3199 {
3200 utab->guards = guardSet_levelUnion (utab->guards,
3201 exprNode_getGuards (pred),
3202 utab->lexlevel);
3203 }
3204
3205 DPRINTF (("Here."));
3206}
3207
3208static void usymtab_fixCases (void) /*@modifies utab@*/ {
3209 while (utab->kind == US_CBRANCH)
3210 {
3211 usymtab_quietPlainExitScope ();
3212 }
3213
3214 llassert (utab->kind != US_CBRANCH);
3215}
3216
3217void
3218usymtab_altBranch (/*@only@*/ guardSet guards)
3219 /*@modifies utab@*/
3220{
3221 usymtab t;
3222 usymtab parent = utab->env;
3223
3224 t = usymtab_create (US_FBRANCH, utab, FALSE);
3225
3226 /*
3227 ** If we are in a case, need to close it. The C syntax
3228 ** is very liberal, so this kludge is necessary.
3229 */
3230
3231 usymtab_fixCases ();
3232
3233 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3234
3235 llassert (utab->kind == US_TBRANCH);
3236 llassert (parent != GLOBAL_ENV);
3237
3238 guardSet_free (t->guards);
3239 t->guards = guards;
3240
3241 aliasTable_free (t->aliases);
3242 t->aliases = aliasTable_copy (parent->aliases);
3243
3244 utab = t;
3245}
3246
3247void
3248usymtab_allDefined (void)
3249 /*@globals utab, globtab@*/
3250{
3251 int i;
3252
3253 llassert (utab == globtab);
3254
3255 for (i = 0; i < utab->nentries; i++)
3256 {
3257 uentry e = utab->entries[i];
3258
3259 if (uentry_isPriv (e))
3260 {
3261 ; /* no need to define it */
3262 }
3263 else
3264 {
3265 if (context_getFlag (FLG_SPECUNDECL))
3266 {
3267 fileloc sloc = uentry_whereSpecified (e);
3268 fileloc dloc = uentry_whereDeclared (e);
3269
3270 if (fileloc_isDefined (sloc)
3271 && !uentry_isFakeTag (e)
3272 && !fileloc_isDefined (dloc))
3273 {
3274 voptgenerror
3275 (FLG_SPECUNDECL,
3276 message ("%s %q specified but not declared",
3277 ekind_capName (uentry_getKind (e)),
3278 uentry_getName (e)),
3279 sloc);
3280 }
3281 }
3282
3283 if (!uentry_isCodeDefined (e))
3284 {
3285 fileloc dloc = uentry_whereDeclared (e);
3286
3287 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3288 {
3289 ;
3290 }
3291 else if (fileloc_isDefined (dloc))
3292 {
3293 if (!uentry_isAnyTag (e))
3294 {
3295 if (fileloc_isUser (dloc))
3296 {
3297 voptgenerror
3298 (FLG_DECLUNDEF,
3299 message ("%s %q declared but not defined",
3300 ekind_capName (uentry_getKind (e)),
3301 uentry_getName (e)),
3302 dloc);
3303 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3304 }
3305 }
3306 }
3307 else
3308 {
3309 fileloc sloc = uentry_whereSpecified (e);
3310
3311 if (fileloc_isDefined (sloc)
3312 && !fileloc_isImport (sloc)
3313 && !fileloc_isLib (sloc)
3314 && !fileloc_isPreproc (sloc)
3315 && !uentry_isFakeTag (e))
3316 {
3317 if (uentry_isVariable (e) || uentry_isFunction (e))
3318 {
3319 voptgenerror
3320 (FLG_SPECUNDEF,
3321 message ("%s %q specified but not declared or defined",
3322 ekind_capName (uentry_getKind (e)),
3323 uentry_getName (e)),
3324 sloc);
3325 }
3326 else
3327 {
3328 voptgenerror
3329 (FLG_SPECUNDEF,
3330 message ("%s %q specified but not defined",
3331 ekind_capName (uentry_getKind (e)),
3332 uentry_getName (e)),
3333 sloc);
3334 }
3335 }
3336 }
3337 }
3338 }
3339 }
3340}
3341
3342void usymtab_exportHeader (void)
3343 /*@globals utab@*/
3344{
3345 int i;
3346
3347 for (i = 0; i < utab->nentries; i++)
3348 {
3349 uentry ce = utab->entries[i];
3350
3351 if (!uentry_isDatatype (ce)
3352 && !uentry_isAnyTag (ce)
3353 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3354 && !uentry_isExternal (ce)
3355 && !uentry_isForward (ce))
3356 {
3357 fileloc fwhere = uentry_whereDeclared (ce);
3358
3359 if (fileloc_isUndefined (fwhere)
3360 && uentry_isFunction (ce))
3361 {
3362 fwhere = uentry_whereDefined (ce);
3363 }
3364
3365 if (fileloc_isDefined (fwhere)
3366 && !fileloc_isHeader (fwhere)
3367 && !fileloc_isXHFile (fwhere)
3368 && !(fileloc_isSpecialFile (fwhere)
3369 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3370 {
3371 if (uentry_isVariable (ce))
3372 {
3373 if (optgenerror
3374 (FLG_EXPORTHEADERVAR,
3375 message ("%s %q exported but not declared in header file",
3376 ekind_capName (uentry_getKind (ce)),
3377 uentry_getName (ce)),
3378 fwhere))
3379 {
3380 uentry_showDefSpecInfo (ce, fwhere);
3381 }
3382 }
3383 else
3384 {
3385 if (!uentry_isIter (ce)
3386 && !uentry_isEndIter (ce)
3387 && !uentry_isExpandedMacro (ce))
3388 {
3389 if (uentry_isFunction (ce)
3390 && cstring_equalLit (uentry_rawName (ce), "main"))
3391 {
3392 ; /* no error for main */
3393 }
3394 else
3395 {
3396 if (optgenerror
3397 (FLG_EXPORTHEADER,
3398 message ("%s %q exported but not declared "
3399 "in header file",
3400 ekind_capName (uentry_getKind (ce)),
3401 uentry_getName (ce)),
3402 fwhere))
3403 {
3404 uentry_showDefSpecInfo (ce, fwhere);
3405 }
3406 }
3407 }
3408 }
3409 }
3410 }
3411 }
3412}
3413
3414void usymtab_exportLocal (void)
3415 /*@globals utab@*/
3416{
3417 int i;
3418
3419 for (i = 0; i < utab->nentries; i++)
3420 {
3421 uentry ce = utab->entries[i];
3422
3423 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3424 && !uentry_isEitherConstant (ce)
3425 && !uentry_isIter (ce)
3426 && !uentry_isEndIter (ce)
3427 && !uentry_isExpandedMacro (ce)
3428 && uentry_isUsed (ce))
3429 {
3430 /* check static uses */
3431 filelocList fuses = uentry_getUses (ce);
3432 fileloc mod = uentry_whereDefined (ce);
3433 bool ok = filelocList_isEmpty (fuses);
3434 fileloc fwhere = uentry_whereDeclared (ce);
3435
3436 if (fileloc_isSpecialFile (fwhere)
3437 && !context_getFlag (FLG_UNUSEDSPECIAL))
3438 {
3439 ok = TRUE; /* no errors for special files */
3440 }
3441 else
3442 {
3443 filelocList_elements (fuses, uloc)
3444 {
3445 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3446 {
3447 ok = TRUE;
3448 /*@innerbreak@*/ break;
3449 }
3450 } end_filelocList_elements;
3451 }
3452
3453 if (!ok)
3454 {
3455 if (optgenerror
3456 (FLG_EXPORTLOCAL,
3457 message ("%s exported but not used outside %s: %q",
3458 ekind_capName (uentry_getKind (ce)),
3459 fileloc_getBase (mod),
3460 uentry_getName (ce)),
3461 fwhere))
3462 {
3463 uentry_showDefSpecInfo (ce, fwhere);
3464 }
3465 }
3466 }
3467 }
3468}
3469
3470void
3471usymtab_allUsed (void)
3472 /*@globals utab@*/
3473{
3474 int i;
3475 bool isFileStatic = usymtab_inFileScope ();
3476 cstring last_file = cstring_undefined;
3477
3478 for (i = 0; i < utab->nentries; i++)
3479 {
3480 bool hasError = FALSE;
3481 uentry ce = utab->entries[i];
3482 fileloc fwhere = uentry_whereDeclared (ce);
3483
3484 if (fileloc_isUndefined (fwhere))
3485 {
3486 fwhere = uentry_whereDefined (ce);
3487 }
3488
3489 if (fileloc_isInvalid (fwhere)
3490 || fileloc_isLib (fwhere)
3491 || fileloc_isBuiltin (fwhere)
3492 || ((fileloc_isSpecialFile (fwhere)
3493 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3494 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3495 {
3496 ;
3497 }
3498 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3499 {
3500 cstring fname = fileloc_filename (fwhere);
3501
3502 if (cstring_isUndefined (last_file))
3503 {
3504 last_file = fname;
3505 }
3506 else if (cstring_equal (fname, last_file))
3507 {
3508 }
3509 else
3510 {
3511 cleanupMessages ();
3512 last_file = fname;
3513 }
3514
3515 if (uentry_isParam (ce))
3516 {
3517 if (context_inMacro ())
3518 {
3519 sRef cref = uentry_getSref (ce);
3520
3521 if (uentry_isYield (ce))
3522 {
3523 ; /* no checks (for now) */
3524 }
3525 else if (sRef_isSafe (cref))
3526 {
3527 ; /* no error */
3528 }
3529 else
3530 {
3531 if (uentry_hasRealName (ce))
3532 {
3533 hasError =
3534 optgenerror (FLG_MACROPARAMS,
3535 message ("Macro parameter %q not used",
3536 uentry_getName (ce)),
3537 fwhere);
3538 }
3539 }
3540 }
3541 else
3542 {
3543 if (cstring_equalFree (uentry_getName (ce),
3544 cstring_makeLiteral ("...")))
3545 {
3546 ;
3547 }
3548 else
3549 {
3550 hasError = optgenerror (FLG_PARAMUNUSED,
3551 message ("Parameter %q not used",
3552 uentry_getName (ce)),
3553 fwhere);
3554 }
3555 }
3556 } /* isParam */
3557 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3558 {
3559 if (fileloc_isUser (fwhere))
3560 {
3561 hasError = optgenerror
3562 (FLG_FUNCUNUSED,
3563 message ("%q %q declared but not used",
3564 cstring_makeLiteral
3565 (uentry_isIter (ce) ? "Iterator"
3566 : (isFileStatic ? "File static function" : "Function")),
3567 uentry_getName (ce)),
3568 fwhere);
3569 }
3570 }
3571 else if (uentry_isEndIter (ce))
3572 {
3573 ; /* no error (already reported for iter */
3574 }
3575 else if (uentry_isEnumConstant (ce))
3576 {
3577 if (fileloc_isUser (fwhere))
3578 {
3579 hasError = optgenerror
3580 (FLG_ENUMMEMUNUSED,
3581 message ("Enum member %q not used",
3582 uentry_getName (ce)),
3583 fwhere);
3584 }
3585 }
3586 else if (uentry_isConstant (ce))
3587 {
3588 if (fileloc_isUser (fwhere))
3589 {
3590 hasError = optgenerror
3591 (FLG_CONSTUNUSED,
3592 message ("Constant %q declared but not used",
3593 uentry_getName (ce)),
3594 fwhere);
3595 }
3596 }
3597 else if (uentry_isDatatype (ce))
3598 {
3599 if (fileloc_isUser (fwhere))
3600 {
3601 hasError = optgenerror
3602 (FLG_TYPEUNUSED,
3603 message ("Type %q declared but not used",
3604 uentry_getName (ce)),
3605 fwhere);
3606 }
3607 }
3608 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3609 { /* errors for ref params will be reported in the next scope */
3610 llassertprint (uentry_isVar (ce),
3611 ("ce: %s", uentry_unparseFull (ce)));
3612
3613 if (ctype_isFunction (uentry_getType (ce)))
3614 {
3615 if (fileloc_isUser (fwhere))
3616 {
3617 hasError = optgenerror
3618 (FLG_FUNCUNUSED,
3619 message ("%q %q declared but not used",
3620 cstring_makeLiteral
3621 (isFileStatic ? "File static function"
3622 : "Function"),
3623 uentry_getName (ce)),
3624 fwhere);
3625 }
3626 }
3627 else
3628 {
3629 if (fileloc_isUser (fwhere))
3630 {
3631
3632
3633 hasError = optgenerror
3634 (FLG_VARUNUSED,
3635 message ("%q %q declared but not used",
3636 cstring_makeLiteral
3637 (isFileStatic ? "File static variable"
3638 : "Variable"),
3639 uentry_getName (ce)),
3640 fwhere);
3641 }
3642 }
3643 }
3644 else
3645 {
3646 ; /* no errors */
3647 }
3648 } /* unused */
3649 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3650 { /* check all fields */
3651 ctype ct = uentry_getRealType (ce);
3652
3653
3654 while (ctype_isAP (ct))
3655 {
3656 ct = ctype_getBaseType (ct);
3657 }
3658
3659 if (ctype_isSU (ct))
3660 {
3661 uentryList fields = ctype_getFields (ct);
3662
3663 uentryList_elements (fields, field)
3664 {
3665 if (!uentry_isUsed (field))
3666 {
3667 if (uentry_hasName (ce))
3668 {
3669 hasError |= optgenerror
3670 (FLG_FIELDUNUSED,
3671 message ("Field %q of %s %q declared but not used",
3672 uentry_getName (field),
3673 cstring_makeLiteralTemp
3674 (ctype_isStruct (ct) ? "structure" : "union"),
3675 uentry_getName (ce)),
3676 uentry_whereEarliest (field));
3677 }
3678 else
3679 {
3680 /*
3681 ** evans 2001-06-08
3682 ** Can't report these errors for unnamed structs.
3683 ** No way to tell when there are multiple consistent
3684 ** unnamed structure types. (Could go through table
3685 ** and mark them all unused...)
3686
3687 hasError |= optgenerror
3688 (FLG_FIELDUNUSED,
3689 message ("Field %q of unnamed %s declared but not used",
3690 uentry_getName (field),
3691 cstring_makeLiteralTemp
3692 (ctype_isStruct (ct) ? "structure" : "union")),
3693 uentry_whereEarliest (field));
3694
3695 */
3696 }
3697
3698 uentry_setUsed (field, fileloc_undefined);
3699 }
3700 } end_uentryList_elements;
3701 }
3702 }
3703 else
3704 {
3705 ; /* no errors */
3706 }
3707
3708 if (hasError)
3709 {
3710 if (uentry_isParam (ce) && context_inMacro ())
3711 {
3712 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3713 {
3714 uentry_showWhereSpecified (ce);
3715 }
3716 }
3717 else
3718 {
3719 uentry_showDefSpecInfo (ce, fwhere);
3720 }
3721
3722 uentry_setUsed (ce, fileloc_undefined);
3723 }
3724 }
3725}
3726
3727static void
3728checkGlobalReturn (uentry glob, sRef orig)
3729{
3730 sRef sr = uentry_getSref (glob);
3731
3732 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3733 uentry_unparseFull (glob),
3734 sRef_unparseFull (orig),
3735 sRef_unparseFull (sr)));
3736
3737 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3738
3739 if (context_getFlag (FLG_GLOBSTATE))
3740 {
3741 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3742
3743 if (sRef_isKilledGlob (orig))
3744 {
3745 if (sRef_isStateUndefined (sr)
3746 || sRef_isUnuseable (sr)
3747 || sRef_isStateUnknown (sr)
3748 || sRef_isDead (sr))
3749 {
3750 ;
3751 }
3752 else
3753 {
3754 ctype ct = ctype_realType (uentry_getType (glob));
3755
3756 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3757
3758 if (ctype_isVisiblySharable (ct))
3759 {
3760 if (optgenerror
3761 (FLG_GLOBSTATE,
3762 message
3763 ("Killed global %q (type %s) not released before return",
3764 uentry_getName (glob),
3765 ctype_unparse (ct)),
3766 g_currentloc))
3767 {
3768 sRef_showStateInfo (sr);
3769 }
3770 }
3771 else
3772 {
3773 sRef_protectDerivs ();
3774 (void) transferChecks_globalDestroyed (sr, g_currentloc);
3775 sRef_clearProtectDerivs ();
3776 }
3777 }
3778 }
3779 else
3780 {
3781 if (sRef_isStateUndefined (sr))
3782 {
3783 if (optgenerror (FLG_GLOBSTATE,
3784 message
3785 ("Function returns with global %q undefined",
3786 uentry_getName (glob)),
3787 g_currentloc))
3788 {
3789 sRef_showStateInfo (sr);
3790 }
3791 }
3792 else
3793 {
3794 if (sRef_isDead (sr) || sRef_isKept (sr))
3795 {
3796 if (optgenerror
3797 (FLG_GLOBSTATE,
3798 message ("Function returns with global %q "
3799 "referencing %s storage",
3800 uentry_getName (glob),
3801 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3802 g_currentloc))
3803 {
3804 if (sRef_isKept (sr))
3805 {
3806 sRef_showAliasInfo (sr);
3807 }
3808 else
3809 {
3810 sRef_showStateInfo (sr);
3811 }
3812
3813 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3814 }
3815 }
3816
3817 DPRINTF (("Here: %s / %s",
3818 uentry_unparseFull (glob),
3819 sRef_unparseFull (sr)));
3820
3821 if (ctype_isRealPointer (uentry_getType (glob))
3822 && sRef_possiblyNull (sr)
3823 && !uentry_possiblyNull (glob))
3824 {
3825 if (optgenerror
3826 (FLG_GLOBSTATE,
3827 message ("Function returns with non-null global %q "
3828 "referencing null storage",
3829 uentry_getName (glob)),
3830 g_currentloc))
3831 {
3832 sRef_showNullInfo (sr);
3833 }
3834 }
3835 else
3836 {
3837 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3838 transferChecks_globalReturn (glob);
3839 }
3840 }
3841 }
3842 }
3843}
3844
3845/*
3846** remember: check alias globals
3847*/
3848
3849void usymtab_checkFinalScope (bool isReturn)
3850 /*@globals utab@*/
3851{
3852 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3853 sRefSet checked = sRefSet_new ();
3854 usymtab stab = utab;
3855 int i;
3856
3857 /*
3858 ** need to check all scopes out to function parameters.
3859 */
3860
3861 do
3862 {
3863 for (i = 0; i < stab->nentries; i++)
3864 {
3865 uentry ce = stab->entries[i];
3866 sRef sr = uentry_getSref (ce);
3867 sRef rb = sRef_getRootBase (sr);
3868 valueTable tvalues;
3869
3870 /*
3871 ** Shouldn't check if shadow checked in deeper scope:
3872 */
3873
3874 if (stab != utab)
3875 {
3876 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3877
3878 if (!uentry_sameObject (ce, oue))
3879 {
3880 /* what if it is one an alternate branch? */
3881 /*@innercontinue@*/ continue;
3882 }
3883 }
3884
3885 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3886
3887 if (ctype_isFunction (uentry_getType (ce)))
3888 {
3889 /*@innercontinue@*/ continue;
3890 }
3891
3892 if (uentry_isAnyParam (ce)
3893 || uentry_isRefParam (ce)
3894 || sRef_isFileOrGlobalScope (rb))
3895 {
3896 /* Don't do the loseref check...but should check state! */
3897 DPRINTF (("Skipping check 1"));
3898 }
3899 else if (sRef_isDefinitelyNull (sr)
3900 || usymtab_isDefinitelyNull (sr))
3901 {
3902 /*
3903 ** No state reference errors for definitely null references.
3904 */
3905
3906 DPRINTF (("Skipping check 2"));
3907 }
3908 else
3909 {
3910 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3911 sRef_unparseFull (sr)));
3912
3913 tvalues = sRef_getValueTable (sr);
3914
3915 valueTable_elements (tvalues, fkey, fval) {
3916 metaStateInfo minfo;
3917 cstring msg = cstring_undefined;
3918 int nval;
3919
3920 minfo = context_lookupMetaStateInfo (fkey);
3921 llassert (metaStateInfo_isDefined (minfo));
3922
3923 if (stateValue_isError (fval)
3924 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3925 {
3926 DPRINTF (("Skipping check 3"));
3927 }
3928 else
3929 {
3930 DPRINTF (("Check: %s / %s / %s", fkey,
3931 metaStateInfo_unparse (minfo),
3932 stateValue_unparse (fval)));
3933
3934 minfo = context_lookupMetaStateInfo (fkey);
3935
3936 nval = stateCombinationTable_lookupLoseReference
3937 (metaStateInfo_getTransferTable (minfo),
3938 stateValue_getValue (fval), &msg);
3939
3940 if (cstring_isDefined (msg))
3941 {
3942 if (optgenerror
3943 (FLG_STATETRANSFER,
3944 message
3945 ("%s loses reference %q in invalid state %q (%s)",
3946 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3947 uentry_getName (ce),
3948 stateValue_unparseValue (fval, minfo),
3949 msg),
3950 g_currentloc))
3951 {
3952 stateValue_show (fval, minfo);
3953 }
3954 else
3955 {
3956 DPRINTF (("Suppressed transfer error: %s", msg));
3957 }
3958 }
3959 }
3960 } end_valueTable_elements;
3961 }
3962
3963 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3964
3965 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3966 {
3967 if (ctype_isRealSU (uentry_getType (ce))
3968 && !uentry_isAnyParam (ce)
3969 && !uentry_isRefParam (ce)
3970 && !uentry_isStatic (ce)
3971 && !sRef_isDependent (sr)
3972 && !sRef_isOwned (sr))
3973 {
3974 sRefSet als = usymtab_allAliases (sr);
3975
3976 if (sRefSet_isEmpty (als))
3977 {
3978 transferChecks_localDestroyed (sr, g_currentloc);
3979 }
3980 else
3981 {
3982 /* aliased, no problem */ ;
3983 }
3984
3985 sRefSet_free (als);
3986 }
3987 else if
3988 (!uentry_isStatic (ce)
3989 && ((sRef_isNewRef (sr))
3990 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3991 || sRef_isKeep (sr) || sRef_isOwned (sr))
3992 && !sRef_isDead (sr))
3993 && (!sRef_definitelyNull (sr))
3994 && (!usymtab_isDefinitelyNull (sr)))))
3995 {
3996 bool hasError = TRUE;
3997
3998 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3999
4000 /*
4001 ** If its a scope exit, check if there is an alias.
4002 ** If so, make it only. If not, there is an error.
4003 */
4004
4005 if (!isReturn)
4006 {
4007 if (transferChecks_canLoseReference (sr, g_currentloc))
4008 {
4009 DPRINTF (("Can lose!"));
4010 hasError = FALSE;
4011 }
4012 }
4013
4014 if (hasError)
4015 {
4016 if (sRef_hasLastReference (sr))
4017 {
4018 sRef ar = sRef_getAliasInfoRef (sr);
4019
4020 if (optgenerror
4021 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4022 message
4023 ("Last reference %q to %s storage %qnot %q before %q",
4024 sRef_unparse (sr),
4025 alkind_unparse (sRef_getAliasKind (sr)),
4026 sRef_unparseOpt (ar),
4027 cstring_makeLiteral (sRef_isKeep (sr)
4028 ? "transferred" : "released"),
4029 cstring_makeLiteral (isReturn
4030 ? "return" : "scope exit")),
4031 g_currentloc))
4032 {
4033 sRef_showRefLost (sr);
4034 }
4035 }
4036 else if (sRef_isNewRef (sr))
4037 {
4038 if (optgenerror
4039 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4040 message
4041 ("%q %q not released before %q",
4042 cstring_makeLiteral
4043 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4044 ? "Kill reference parameter" : "New reference"),
4045 uentry_getName (ce),
4046 cstring_makeLiteral (isReturn
4047 ? "return" : "scope exit")),
4048 g_currentloc))
4049 {
4050 sRef_showAliasInfo (sr);
4051 }
4052 }
4053 else
4054 {
4055 if (ctype_isRealSU (sRef_getType (sr)))
4056 {
4057 transferChecks_structDestroyed (sr, g_currentloc);
4058 }
4059 else
4060 {
4061 if (optgenerror
4062 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4063 message
4064 ("%s storage %q not %q before %q",
4065 alkind_capName (sRef_getAliasKind (sr)),
4066 uentry_getName (ce),
4067 cstring_makeLiteral (sRef_isKeep (sr)
4068 ? "transferred" : "released"),
4069 cstring_makeLiteral (isReturn
4070 ? "return" : "scope exit")),
4071 g_currentloc))
4072 {
4073 sRef_showAliasInfo (sr);
4074 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4075 }
4076 }
4077 }
4078 }
4079 }
4080 else
4081 {
4082 ;
4083 }
4084 }
4085
4086 if (mustDefine && uentry_isOut (ce))
4087 {
4088 /* No error if its dead (either only or error already reported */
4089 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4090 {
4091 voptgenerror
4092 (FLG_MUSTDEFINE,
4093 message ("Out storage %q not defined before %q",
4094 uentry_getName (ce),
4095 cstring_makeLiteral
4096 (isReturn ? "return" : "scope exit")),
4097 g_currentloc);
4098
4099 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4100 }
4101 }
4102
4103 /*
4104 ** also check state is okay
4105 */
4106
4107 if (usymtab_lexicalLevel () > functionScope
4108 && uentry_isVariable (ce)
4109 && (sRef_isLocalVar (sr)
4110 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4111 {
4112 sRefSet ab = usymtab_aliasedBy (sr);
4113
4114 /* should do something more efficient here */
4115
4116 if (sRefSet_isEmpty (ab))
4117 {
4118 /* and no local ref */
4119 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4120 transferChecks_loseReference (ce);
4121 }
4122 else
4123 {
4124 ;
4125 }
4126
4127 sRefSet_free (ab);
4128 }
4129 else
4130 {
4131 ;
4132 }
4133
4134 checked = sRefSet_insert (checked, sr);
4135 }
4136
4137 llassert (usymtab_isDefined (stab->env));
4138
4139 if (usymtab_isBranch (stab))
4140 {
4141 stab = usymtab_dropEnv (stab);
4142 }
4143 else
4144 {
4145 stab = stab->env;
4146 }
4147
4148 llassert (stab != usymtab_undefined);
4149 } while (isReturn && (stab->lexlevel >= paramsScope));
4150
4151 sRefSet_free (checked);
4152
4153 /*
4154 ** for returns:
4155 ** all globals are appropriately defined
4156 ** all parameters are appropriately defined
4157 ** special clauses are followed
4158 */
4159
4160 if (isReturn || (utab->lexlevel == paramsScope))
4161 {
4162 uentry fcn = context_getHeader ();
4163 uentryList params = context_getParams ();
4164 globSet uglobs = context_getUsedGlobs ();
4165 globSet sglobs = context_getGlobs ();
4166
4167 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4168 {
4169 aliasTable_checkGlobs (utab->aliases);
4170 }
4171
4172 /*
4173 ** state clauses (ensures, defines, sets, allocates, releases)
4174 */
4175
4176 if (uentry_hasStateClauseList (fcn))
4177 {
4178 stateClauseList clauses = uentry_getStateClauseList (fcn);
4179
4180 stateClauseList_elements (clauses, cl)
4181 {
4182 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4183 {
4184 if (stateClause_setsMetaState (cl))
4185 {
4186 sRefSet rfs = stateClause_getRefs (cl);
4187 qual q = stateClause_getMetaQual (cl);
4188 annotationInfo ainfo = qual_getAnnotationInfo (q);
4189 metaStateInfo minfo = annotationInfo_getState (ainfo);
4190 cstring key = metaStateInfo_getName (minfo);
4191 int mvalue = annotationInfo_getValue (ainfo);
4192
4193 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4194
4195 sRefSet_elements (rfs, el)
4196 {
4197 sRef base = sRef_getRootBase (el);
4198
4199 if (sRef_isResult (base))
4200 {
4201 /*
4202 ** This is checked for return transfers.
4203 */
4204 ;
4205 }
4206 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4207 {
4208 sRef sr = sRef_updateSref (base);
4209 sr = sRef_fixBase (el, sr);
4210
4211 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4212 {
4213 if (optgenerror
4214 (FLG_STATETRANSFER,
4215 message
4216 ("Ensures clause not satisfied%q (state is %q): %q",
4217 sRef_isGlobalMarker (sr)
4218 ? message ("")
4219 : message (" by %q", sRef_unparse (sr)),
4220 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4221 minfo),
4222 stateClause_unparse (cl)),
4223 g_currentloc))
4224 {
4225 sRef_showMetaStateInfo (sr, key);
4226 }
4227 }
4228 }
4229 else
4230 {
4231 if (sRef_isMeaningful (el))
4232 {
4233 BADBRANCH;
4234 }
4235 }
4236 } end_sRefSet_elements ;
4237 }
4238 else
4239 {
4240 /* evs - 2000 07 10 - added this */
4241 sRefTest tst = stateClause_getPostTestFunction (cl);
4242 sRefSet rfs = stateClause_getRefs (cl);
4243
4244 sRefSet_elements (rfs, el)
4245 {
4246 sRef base = sRef_getRootBase (el);
4247
4248 if (sRef_isResult (base))
4249 {
4250 /*
4251 ** This is checked for return transfers.
4252 */
4253
4254 ;
4255 }
4256 else if (sRef_isParam (base))
4257 {
4258 sRef sr = sRef_updateSref (base);
4259 sr = sRef_fixBase (el, sr);
4260
4261 if (tst != NULL && !tst (sr))
4262 {
4263 if (optgenerror
4264 (stateClause_postErrorCode (cl),
4265 message ("%s storage %qcorresponds to "
4266 "storage listed in %q clause",
4267 stateClause_postErrorString (cl, sr),
4268 sRef_unparseOpt (sr),
4269 stateClause_unparseKind (cl)),
4270 g_currentloc))
4271 {
4272 sRefShower ss = stateClause_getPostTestShower (cl);
4273
4274 if (ss != NULL)
4275 {
4276 ss (sr);
4277 }
4278
4279 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4280 }
4281 }
4282 }
4283 else
4284 {
4285 if (sRef_isMeaningful (el))
4286 {
4287 BADBRANCH;
4288 }
4289 }
4290 } end_sRefSet_elements ;
4291 }
4292 }
4293 } end_stateClauseList_elements ;
4294 }
4295
4296 /*
4297 ** check parameters on return
4298 */
4299
4300 uentryList_elements (params, arg)
4301 {
4302 if (!uentry_isElipsisMarker (arg))
4303 {
4304 ctype rt = ctype_realType (uentry_getType (arg));
4305
4306 if (ctype_isMutable (rt) || ctype_isSU (rt))
4307 {
4308 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4309 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4310 transferChecks_paramReturn (param);
4311 }
4312 }
4313 } end_uentryList_elements;
4314
4315 DPRINTF (("Check global return: %s",
4316 globSet_unparse (sglobs)));
4317
4318 globSet_allElements (sglobs, el)
4319 {
4320 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4321 uentry current = sRef_getUentry (el);
4322
4323 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4324 uentry_unparseFull (current)));
4325
4326 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4327 {
4328 checkGlobalReturn (current, orig);
4329 }
4330 } end_globSet_allElements;
4331
4332 globSet_allElements (uglobs, el)
4333 {
4334 if (!globSet_member (sglobs, el))
4335 {
4336 uentry current = sRef_getUentry (el);
4337
4338 if (uentry_isVariable (current)
4339 && !uentry_isRealFunction (current))
4340 {
4341 checkGlobalReturn (current, sRef_undefined);
4342 }
4343 }
4344 } end_globSet_allElements;
4345 }
4346}
4347
4348void
4349usymtab_quietExitScope (fileloc loc)
4350 /*@globals utab, globtab, filetab; @*/
4351 /*@modifies utab@*/
4352{
4353 usymtab t = utab->env;
4354
4355 DPRINTF (("Quiet exit scope [%p]", utab));
4356
4357 if (utab->reftable != NULL)
4358 {
4359 int i;
4360
4361 for (i = 0; i < utab->nentries; i++)
4362 {
4363 uentry current = utab->entries[i];
4364 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4365
4366 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4367 }
4368 }
4369
4370 llassert (t != NULL);
4371
4372 if (t->lexlevel > paramsScope)
4373 {
4374 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4375 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4376 t->lexlevel);
4377 utab->aliases = aliasTable_undefined;
4378 }
4379
4380 t->mustBreak = utab->mustBreak;
4381 t->exitCode = utab->exitCode;
4382
4383 DPRINTF (("Free level [%p]", utab));
4384 usymtab_freeLevel (utab);
4385
4386 utab = t;
4387
4388# ifdef DEBUGSPLINT
4389 usymtab_checkAllValid ();
4390# endif
4391}
4392
4393/*
4394** Exit a scope with no checking, lose alias states.
4395** (When should this be used?)
4396*/
4397
4398void usymtab_quietPlainExitScope (void)
4399 /*@globals utab, globtab, filetab@*/
4400 /*@modifies utab@*/
4401{
4402 usymtab t = utab->env;
4403
4404 llassert (t != NULL);
4405 llassert (NOALIAS (utab->aliases, t->aliases));
4406 usymtab_freeLevel (utab);
4407 utab = t;
4408}
4409
4410void usymtab_exitScope (exprNode expr)
4411 /*@globals utab, filetab, globtab@*/
4412 /*@modifies utab, globtab@*/
4413{
4414 usymtab ctab = usymtab_undefined;
4415 usymtab lctab = usymtab_undefined;
4416 bool mustReturn = exprNode_mustEscape (expr);
4417
4418 DPRINTF (("Exit scope [%p]", utab));
4419
4420 if (utab->kind == US_CBRANCH)
4421 {
4422 /*
4423 ** save the case branches, remove the first non-cbranch
4424 */
4425
4426 ctab = utab;
4427
4428 while (utab->kind == US_CBRANCH)
4429 {
4430 lctab = utab;
4431 utab = utab->env;
4432 llassert (utab != GLOBAL_ENV);
4433 }
4434 }
4435
4436 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4437 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH)
4438 {
4439 if (context_inMacro ())
4440 {
4441 /* evs 2000-07-25 */
4442 /* Unparseable macro may end inside nested scope. Deal with it. */
4443
4444 llerror (FLG_SYNTAX,
4445 message ("Problem parsing macro body of %s (unbalanced scopes). "
4446 "Attempting to recover, recommend /*@notfunction@*/ before "
4447 "macro definition.",
4448 context_inFunctionName ()));
4449
4450 while (utab->kind == US_TBRANCH
4451 || utab->kind == US_FBRANCH
4452 || utab->kind == US_CBRANCH
4453 || utab->kind == US_SWITCH)
4454 {
4455 utab = utab->env;
4456 llassert (utab != GLOBAL_ENV);
4457 }
4458 } else
4459 {
4460 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4461 /*@-branchstate@*/
4462 } /*@=branchstate@*/
4463 }
4464
4465 /*
4466 ** check all variables in scope were used
4467 */
4468
4469 /*
4470 ** bogus errors if this is the normal inside a switch,
4471 ** since cases have not been merged yet. Should probably
4472 ** still check this, but I'm too lazy at the moment...
4473 */
4474
4475 llassertfatal (utab->env != GLOBAL_ENV);
4476
4477 if (utab->env->kind != US_SWITCH)
4478 {
4479 usymtab_allUsed ();
4480 }
4481
4482 /*
4483 ** check aliasing: all only params are released (dead)
4484 ** definition: all out params are defined, all modified params
4485 ** are completely defined
4486 **
4487 ** NOTE: note for exiting paramsScope, since checkReturn should be
4488 ** called first.
4489 */
4490
4491 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4492 {
4493 /*
4494 ** should only call this is end of scope is reachable...
4495 */
4496
4497 usymtab_checkFinalScope (FALSE);
4498 }
4499
4500 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4501 {
4502 /*
4503 ** leaving a function, need to fix up globals
4504 */
4505
4506 uentryList params = context_getParams ();
4507 globSet globs = context_getUsedGlobs ();
4508
4509 uentryList_elements (params, ue)
4510 {
4511 uentry_fixupSref (ue);
4512 } end_uentryList_elements;
4513
4514 clearFunctionTypes ();
4515
4516 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4517
4518 globSet_allElements (globs, el)
4519 {
4520 DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4521
4522 if (sRef_isCvar (el))
4523 {
4524 uentry current;
4525 usymId index = sRef_getScopeIndex (el);
4526
4527 if (sRef_isFileStatic (el))
4528 {
4529 llassert (usymtab_isDefined (filetab));
4530 current = usymtab_fetchIndex (filetab, index);
4531 }
4532 else
4533 {
4534 current = usymtab_fetchIndex (globtab, index);
4535 }
4536
4537 if (uentry_isVariable (current))
4538 {
4539 DPRINTF (("Fixup: %s", uentry_unparse (current)));
4540 uentry_fixupSref (current);
4541 }
4542 else
4543 {
4544 DPRINTF (("Clear: %s", uentry_getSref (current)));
4545 sRef_clearDerived (uentry_getSref (current));
4546 }
4547 }
4548
4549 sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4550 } end_globSet_allElements;
4551 }
4552
4553 usymtab_quietExitScope (exprNode_loc (expr));
4554
4555 if (lctab != usymtab_undefined)
4556 {
4557 /*@i@*/ lctab->env = utab;
4558 /*@i@*/ utab = ctab;
4559 /*@-branchstate@*/ } /*@=branchstate@*/
4560 /*@-globstate@*/
4561
4562
4563# ifdef DEBUGSPLINT
4564 usymtab_checkAllValid ();
4565# endif
4566}
4567/*@=globstate@*/
4568
4569/*
4570** yikes! don't let the '170 kids see this one...
4571*/
4572
4573usymId
4574usymtab_directParamNo (uentry ue)
4575{
4576 if (uentry_isVar (ue))
4577 {
4578 sRef sr = uentry_getSref (ue);
4579
4580 if (sRef_lexLevel (sr) == functionScope)
4581 {
4582 usymId index = sRef_getScopeIndex (sr);
4583
4584 if (index < usymId_fromInt (uentryList_size (context_getParams ())))
4585 {
4586 return index;
4587 }
4588 }
4589 }
4590 return usymId_invalid;
4591}
4592
4593/*@dependent@*/ /*@exposed@*/ uentry
4594 usymtab_getParam (int paramno)
4595 /*@globals utab@*/
4596{
4597 /*
4598 ** requires in a function context (checked)
4599 **
4600 ** depends on no nested functions --- the function
4601 ** parameters are ALWAYS one scope inside the global scope
4602 ** and entered in order!
4603 */
4604 usymtab s = utab;
4605
4606 if (!context_inFunctionLike ())
4607 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4608 context_unparse ()));
4609
4610 while (s->lexlevel > paramsScope)
4611 {
4612 s = s->env;
4613 }
4614
4615 llassert (usymtab_isDefined (s));
4616
4617 if (paramno >= s->nentries)
4618 {
4619 /*
4620 ** Parse errors lead to this.
4621 */
4622
4623 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4624 ctype_unknown);
4625
4626 uentry_markOwned (err);
4627 return (err);
4628 }
4629
4630 return (s->entries[paramno]);
4631}
4632
4633static /*@dependent@*/ /*@exposed@*/ uentry
4634usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4635{
4636 uentry ue;
4637
4638 ue = usymtab_getRefNoisy (u, level, index);
4639
4640 if (uentry_isUndefined (ue))
4641 {
4642 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4643 index, level));
4644 }
4645
4646 return ue;
4647}
4648
4649static /*@dependent@*/ /*@exposed@*/ usymtab
4650 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4651{
4652 if (s->kind == US_CBRANCH)
4653 {
4654 usymtab t = s;
4655
4656 do
4657 {
4658 t = s;
4659 s = s->env;
4660 llassert (s != GLOBAL_ENV);
4661 } while (s->kind == US_CBRANCH);
4662 /* drop all cases (except in nested scopes */
4663
4664 s = t;
4665 llassert (s != GLOBAL_ENV);
4666 }
4667
4668 if (s->kind == US_FBRANCH)
4669 {
4670 s = s->env; /* skip the true branch */
4671 llassert (usymtab_isDefined (s));
4672 llassert (s->kind == US_TBRANCH);
4673 }
4674
4675 llassert (s != GLOBAL_ENV);
4676 s = s->env;
4677
4678 return s;
4679}
4680
4681/*@dependent@*/ /*@exposed@*/ uentry
4682 usymtab_getRefQuiet (int level, usymId index)
4683 /*@globals utab@*/
4684{
4685 usymtab s = utab;
4686
4687
4688 llassert (s != NULL);
4689 llassert (index >= 0);
4690
4691 if (level > s->lexlevel)
4692 {
4693 return uentry_undefined;
4694 }
4695
4696 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4697 level, s->lexlevel));
4698
4699 while (s->lexlevel > level)
4700 {
4701 if (usymtab_isBranch (s))
4702 {
4703 int eindex = refTable_lookup (s, level, index);
4704
4705 if (eindex != NOT_FOUND)
4706 {
4707 return (s->entries[eindex]);
4708 }
4709 }
4710
4711 s = usymtab_dropEnv (s);
4712 }
4713
4714 while (usymtab_isBranch (s) && s->lexlevel == level)
4715 {
4716 int eindex = refTable_lookup (s, level, index);
4717
4718 if (eindex != NOT_FOUND)
4719 {
4720 return (s->entries[eindex]);
4721 }
4722
4723 s = usymtab_dropEnv (s);
4724 }
4725
4726 if (index >= usymId_fromInt (s->nentries))
4727 {
4728 return uentry_undefined;
4729 }
4730
4731 llassert (!uentry_isUndefined (s->entries[index]));
4732
4733 return s->entries[index];
4734}
4735
4736static /*@dependent@*/ /*@exposed@*/ uentry
4737usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4738{
4739 usymtab otab = s;
4740 uentry ue = uentry_undefined;
4741
4742 llassert (index >= 0);
4743
4744 while (s->lexlevel > level)
4745 {
4746 if (usymtab_isBranch (s))
4747 {
4748 int eindex = refTable_lookup (s, level, index);
4749
4750 if (eindex != NOT_FOUND)
4751 {
4752 ue = s->entries[eindex];
4753
4754 if (s != otab)
4755 {
4756 while (!usymtab_isBranch (otab))
4757 {
4758 otab = usymtab_dropEnv (otab);
4759 llassert (otab != GLOBAL_ENV);
4760 }
4761
4762 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4763 {
4764 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4765 }
4766 else
4767 {
4768 ;
4769 }
4770 }
4771
4772 return ue;
4773 }
4774 }
4775
4776 s = usymtab_dropEnv (s);
4777 }
4778
4779 llassert (usymtab_isDefined (s));
4780
4781 while (usymtab_isBranch (s) && s->lexlevel == level)
4782 {
4783 int eindex = refTable_lookup (s, level, index);
4784
4785 if (eindex != NOT_FOUND)
4786 {
4787 ue = s->entries[eindex];
4788
4789 if (s != otab)
4790 {
4791 while (!usymtab_isBranch (otab))
4792 {
4793 otab = usymtab_dropEnv (otab);
4794 llassert (otab != GLOBAL_ENV);
4795 }
4796
4797 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4798 }
4799 else
4800 {
4801 ;
4802 }
4803
4804 return ue;
4805 }
4806
4807 s = usymtab_dropEnv (s);
4808 }
4809
4810 if (s->lexlevel == level && (index < usymId_fromInt (s->nentries)))
4811 {
4812 ue = s->entries[index];
4813
4814 if (uentry_isValid (ue))
4815 {
4816 if (s != otab)
4817 {
4818 while (!usymtab_isBranch (otab))
4819 {
4820 otab = usymtab_dropEnv (otab);
4821
4822 if (otab == GLOBAL_ENV)
4823 {
4824 return ue;
4825 }
4826 }
4827
4828 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4829 }
4830 else
4831 {
4832 }
4833 }
4834
4835 return ue;
4836 }
4837
4838
4839 if (index >= usymId_fromInt (s->nentries))
4840 {
4841 return uentry_undefined;
4842 }
4843
4844 llassert (!uentry_isUndefined (s->entries[index]));
4845
4846 return s->entries[index];
4847}
4848
4849/*
4850** looking up entries
4851**
4852** If entry is inside a branch, then copy it, and put it into
4853** the branch table.
4854*/
4855
4856static
4857int refTable_lookup (/*@notnull@*/ usymtab ut, int level, usymId index)
4858{
4859 refTable rt = ut->reftable;
4860 int i;
4861
4862 llassert (rt != NULL);
4863
4864 for (i = 0; i < ut->nentries; i++)
4865 {
4866 if (rt[i]->level == level && rt[i]->index == usymId_toInt (index))
4867 {
4868 return i;
4869 }
4870 }
4871
4872 return NOT_FOUND;
4873}
4874
4875static
4876/*@only@*/ refentry refentry_create (int level, int index)
4877{
4878 refentry r = (refentry) dmalloc (sizeof (*r));
4879
4880 r->level = level;
4881 r->index = index;
4882
4883 return r;
4884}
4885
4886static /*@dependent@*/ /*@exposed@*/ uentry
4887usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4888{
4889 usymtab ut = s;
4890
4891 if (ut->reftable == NULL)
4892 {
4893 DPRINTF (("Adding ref entry without reftable: %s", k));
4894 return uentry_undefined;
4895 }
4896
4897 llassert (ut->reftable != NULL);
4898
4899 while (s != GLOBAL_ENV)
4900 {
4901 usymId eindex = usymtab_getIndex (s, k);
4902
4903 if (usymtab_indexFound (eindex))
4904 {
4905 uentry current = s->entries[eindex];
4906
4907 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4908 {
4909 uentry ue;
4910
4911 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4912 if (uentry_isNonLocal (current))
4913 {
4914 ue = uentry_copy (current);
4915 }
4916 else
4917 {
4918 ue = uentry_copyNoSave (current);
4919 }
4920
4921 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4922 usymtab_addEntryQuiet (ut, ue);
4923 DPRINTF (("Okay..."));
4924
4925 if (s->reftable != NULL)
4926 {
4927 refentry ref = s->reftable[eindex];
4928
4929 ut->reftable[ut->nentries - 1]
4930 = refentry_create (ref->level, ref->index);
4931 }
4932 else
4933 {
4934 ut->reftable[ut->nentries - 1]
4935 = refentry_create (s->lexlevel, usymId_toInt (eindex));
4936 }
4937
4938 return (ue);
4939 }
4940 else
4941 {
4942 return (current);
4943 }
4944 }
4945
4946 s = usymtab_dropEnv (s);
4947 }
4948
4949 return uentry_undefined;
4950}
4951
4952static uentry usymtab_lookupAux (usymtab s, cstring k)
4953{
4954 DPRINTF (("Lookup: %s", k));
4955
4956 while (s != GLOBAL_ENV)
4957 {
4958 usymId eindex = usymtab_getIndex (s, k);
4959
4960 if (usymtab_indexFound (eindex))
4961 {
4962 uentry ret = s->entries[eindex];
4963# if 0
4964
4965
4966 if (s->kind == US_TBRANCH
4967 || s->kind == US_FBRANCH
4968 || s->kind == US_CBRANCH)
4969 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4970 {
4971 uentry ret;
4972 DPRINTF (("Adding global ref entry: %s", k));
4973 ret = usymtab_addRefEntry (os, k);
4974 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4975 return ret;
4976 }
4977
4978# endif
4979 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4980 return (ret);
4981 }
4982
4983 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4984 || s->kind == US_CBRANCH)
4985 {
4986 /* why isn't this os??? */
4987 uentry ret = usymtab_addRefEntry (s, k);
4988 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4989 return ret;
4990 }
4991
4992 s = s->env;
4993 }
4994
4995 return uentry_undefined;
4996}
4997
4998static /*@dependent@*/ /*@exposed@*/ uentry
4999usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
5000{
5001 while (s != GLOBAL_ENV)
5002 {
5003 usymId eindex = usymtab_getIndex (s, k);
5004
5005 if (usymtab_indexFound (eindex))
5006 {
5007 uentry ret = s->entries[eindex];
5008 return (ret);
5009 }
5010
5011 if (noalt && usymtab_isBranch (s))
5012 {
5013 s = usymtab_dropEnv (s);
5014 }
5015 else
5016 {
5017 llassert (s != NULL);
5018 s = s->env;
5019 }
5020 }
5021
5022 return uentry_undefined;
5023}
5024
5025static /*@exposed@*/ /*@dependent@*/ uentry
5026usymtab_lookupQuiet (usymtab s, cstring k)
5027{
5028 return usymtab_lookupQuietAux (s, k, FALSE);
5029}
5030
5031static /*@exposed@*/ /*@dependent@*/ uentry
5032usymtab_lookupQuietNoAlt (usymtab s, cstring k)
5033{
5034 return usymtab_lookupQuietAux (s, k, TRUE);
5035}
5036
5037/*@dependent@*/ /*@observer@*/ uentry
5038 usymtab_lookupSafe (cstring k)
5039 /*@globals utab@*/
5040{
5041 DPRINTF (("Lookup safe: %s", k));
5042 return (usymtab_lookupAux (utab, k));
5043}
5044
5045/*@dependent@*/ /*@observer@*/ uentry
5046 usymtab_lookupSafeScope (cstring k, int lexlevel)
5047 /*@globals utab@*/
5048{
5049 /*
5050 ** This is necessary to deal with shadowed variables that are referenced
5051 ** through aliases inside the shadowed scope. It would be better if
5052 ** lookup could take an sRef as a parameter.
5053 */
5054
5055 usymtab tab = utab;
5056
5057 while (tab != GLOBAL_ENV && tab->lexlevel > lexlevel) {
5058 uentry ret = usymtab_lookupAux (tab, k);
5059
5060 if (uentry_isValid (ret)) {
5061 sRef sr = uentry_getSref (ret);
5062
5063 if (sRef_isCvar (sr) && sRef_lexLevel (sr) > lexlevel) {
5064 tab = usymtab_dropEnv (tab);
5065 } else {
5066 return ret;
5067 }
5068 }
5069 }
5070
5071 return uentry_undefined;
5072}
5073
5074uentry
5075 usymtab_lookupExpose (cstring k)
5076 /*@globals utab@*/
5077{
5078 uentry ce = usymtab_lookupAux (utab, k);
5079
5080 if (uentry_isUndefined (ce))
5081 {
5082 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5083 }
5084
5085 if (uentry_isPriv (ce))
5086 {
5087 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5088 }
5089
5090 return ce;
5091}
5092
5093uentry usymtab_lookupExposeGlob (cstring k)
5094{
5095 return (usymtab_lookupGlobSafe (k));
5096}
5097
5098uentry usymtab_lookupGlob (cstring k)
5099 /*@globals globtab@*/
5100{
5101 uentry ce = usymtab_lookupAux (globtab, k);
5102
5103 if (uentry_isUndefined (ce))
5104 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5105
5106 if (uentry_isPriv (ce))
5107 llfatalbug (message ("usymtab_lookup: private: %s", k));
5108
5109 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5110 return ce;
5111}
5112
5113/*@observer@*/ uentry
5114 usymtab_lookupGlobSafe (cstring k)
5115 /*@globals globtab@*/
5116{
5117 uentry ce = usymtab_lookupAux (globtab, k);
5118 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5119 return ce;
5120}
5121
5122uentry usymtab_lookupEither (cstring k)
5123 /*@globals utab@*/
5124{
5125 uentry ce = usymtab_lookupSafe (k);
5126
5127 if (uentry_isUndefined (ce))
5128 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5129
5130 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5131 return ce;
5132}
5133
5134ctype
5135usymtab_lookupType (cstring k)
5136 /*@globals globtab@*/
5137{
5138 typeId uid = usymtab_getTypeId (k);
5139
5140 if (typeId_isInvalid (uid))
5141 {
5142 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5143 return ctype_unknown;
5144 }
5145
5146 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5147}
5148
5149ctype
5150usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5151{
5152 typeId uid = usymtab_getTypeId (k);
5153
5154 if (typeId_isInvalid (uid))
5155 {
5156 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5157 return ctype_unknown;
5158 }
5159
5160 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5161}
5162
5163/*
5164** if there is an unnamed lcl-specified struct tag matching
5165** the uentryList, return its datatype. Otherwise, returns
5166** ctype_undefined.
5167*/
5168
5169ctype
5170usymtab_structFieldsType (uentryList f)
5171 /*@globals globtab@*/
5172{
5173 return (usymtab_suFieldsType (f, TRUE));
5174}
5175
5176ctype
5177usymtab_unionFieldsType (uentryList f)
5178 /*@globals globtab@*/
5179{
5180 return (usymtab_suFieldsType (f, FALSE));
5181}
5182
5183static ctype
5184usymtab_suFieldsType (uentryList f, bool isStruct)
5185 /*@globals globtab@*/
5186{
5187 int i;
5188
5189 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5190
5191 if (fileloc_isSpec (g_currentloc))
5192 {
5193 return (ctype_undefined);
5194 }
5195
5196 for (i = 0; i < globtab->nentries; i++)
5197 {
5198 uentry current = globtab->entries[i];
5199
5200 if ((isStruct
5201 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5202 {
5203 if (isFakeTag (uentry_rawName (current)))
5204 {
5205 ctype ct = uentry_getType (current);
5206
5207 DPRINTF (("Check: %s", ctype_unparse (ct)));
5208
5209 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5210 &&
5211 (uentry_isSpecified (current)
5212 && uentryList_equivFields (f, ctype_getFields (ct))))
5213 {
5214 return uentry_getAbstractType (current);
5215 }
5216 else
5217 {
5218 ;
5219 }
5220 }
5221 }
5222 }
5223
5224 return ctype_undefined;
5225}
5226
5227ctype
5228 usymtab_enumEnumNameListType (enumNameList f)
5229 /*@globals globtab@*/
5230{
5231 int i;
5232
5233 for (i = 0; i < globtab->nentries; i++)
5234 {
5235 uentry current = globtab->entries[i];
5236
5237 if (uentry_isEnumTag (current))
5238 {
5239 if (isFakeTag (uentry_rawName (current)))
5240 {
5241 ctype ct = uentry_getType (current);
5242
5243 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5244 {
5245 return uentry_getType (current);
5246 }
5247 }
5248 }
5249 }
5250
5251 return ctype_undefined;
5252}
5253
5254bool
5255usymtab_exists (cstring k)
5256 /*@globals utab@*/
5257{
5258 uentry ce = usymtab_lookupSafe (k);
5259 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5260}
5261
5262bool
5263usymtab_existsReal (cstring k)
5264 /*@globals utab@*/
5265{
5266 uentry ce = usymtab_lookupSafe (k);
5267
5268 return (!(uentry_isUndefined (ce))
5269 && !(uentry_isPriv (ce))
5270 && !(uentry_isExpandedMacro (ce)));
5271}
5272
5273bool
5274 usymtab_existsGlob (cstring k)
5275 /*@globals globtab@*/
5276{
5277 uentry ce = usymtab_lookupAux (globtab, k);
5278
5279 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5280}
5281
5282bool
5283usymtab_existsEither (cstring k)
5284 /*@globals utab@*/
5285{
5286 uentry ce = usymtab_lookupAux (utab, k);
5287
5288 return (uentry_isValid (ce));
5289}
5290
5291bool
5292 usymtab_existsGlobEither (cstring k)
5293 /*@globals globtab@*/
5294{
5295 uentry ce = usymtab_lookupAux (globtab, k);
5296
5297 return (uentry_isValid (ce));
5298}
5299
5300bool
5301usymtab_existsType (cstring k)
5302 /*@globals globtab@*/
5303{
5304 uentry ce = usymtab_lookupAux (globtab, k);
5305
5306 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5307}
5308
5309bool
5310usymtab_existsTypeEither (cstring k)
5311 /*@globals globtab@*/
5312{
5313 uentry ce;
5314 ce = usymtab_lookupAux (globtab, k);
5315 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5316}
5317
5318bool
5319usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5320{
5321 cstring sname = makeStruct (k);
5322 uentry ce = usymtab_lookupAux (globtab, sname);
5323 cstring_free (sname);
5324 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5325}
5326
5327bool
5328usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5329{
5330 cstring uname = makeUnion (k);
5331 uentry ce = usymtab_lookupAux (globtab, uname);
5332
5333 cstring_free (uname);
5334
5335 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5336}
5337
5338bool
5339usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5340{
5341 cstring ename = makeEnum (k);
5342 uentry ce = usymtab_lookupAux (globtab, ename);
5343
5344 cstring_free (ename);
5345 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5346}
5347
5348bool usymtab_existsVar (cstring k)
5349 /*@globals utab@*/
5350{
5351 uentry ce = usymtab_lookupSafe (k);
5352
5353 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5354}
5355
5356/*
5357** destructors
5358*/
5359
5360static void
5361refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5362{
5363 if (x != NULL)
5364 {
5365 int i;
5366
5367 for (i = 0; i < nentries; i++)
5368 {
5369 sfree (x[i]);
5370 }
5371
5372 sfree (x);
5373 }
5374}
5375
5376static void
5377usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5378 /*@globals globtab, utab, filetab@*/
5379{
5380 int i;
5381
5382 DPRINTF (("Free level [%p]", u));
5383 aliasTable_free (u->aliases);
5384
5385 refTable_free (u->reftable, u->nentries);
5386
5387 if (u == filetab || u == globtab)
5388 {
5389 for (i = 0; i < u->nentries; i++)
5390 {
5391 DPRINTF (("Free complete: %d", i));
5392 DPRINTF (("Uentry: %s", uentry_unparse (u->entries[i])));
5393 uentry_freeComplete (u->entries[i]);
5394 u->entries[i] = uentry_undefined;
5395 }
5396 }
5397 else
5398 {
5399 for (i = 0; i < u->nentries; i++)
5400 {
5401 uentry_free (u->entries[i]);
5402 u->entries[i] = uentry_undefined;
5403 }
5404 }
5405
5406 guardSet_free (u->guards);
5407 sfree (u->entries);
5408
5409 if (u != globtab
5410 && u != utab
5411 && u != filetab)
5412 {
5413 llassert (!cstringTable_isDefined (u->htable));
5414 }
5415
5416 sfree (u); /* evans 2002-07-12: was inside if */
5417}
5418
5419static void
5420usymtab_freeAux (/*@only@*/ usymtab u)
5421 /*@globals globtab, utab, filetab@*/
5422 /*@modifies u@*/
5423{
5424 while (u != GLOBAL_ENV)
5425 {
5426 usymtab t = u->env;
5427 usymtab_freeLevel (u);
5428 u = t;
5429 /*@-branchstate@*/
5430 }
5431 /*@=branchstate@*/
5432}
5433
5434void usymtab_free ()
5435 /*@globals killed utab, globtab, filetab@*/
5436 /*@modifies utab@*/
5437{
5438 dbgfree = TRUE;
5439 usymtab_freeAux (utab);
5440 utab = usymtab_undefined;
5441 /*@-globstate@*/
5442} /*@=globstate@*/ /* Splint cannot tell that utab is killed */
5443
5444static int usymtab_lexicalLevel (void) /*@globals utab@*/
5445{
5446 return (utab->lexlevel);
5447}
5448
5449bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5450{
5451 return (utab == globtab);
5452}
5453
5454bool usymtab_inFileScope () /*@globals utab@*/
5455{
5456 return (utab->lexlevel == fileScope);
5457}
5458
5459bool usymtab_inFunctionScope () /*@globals utab@*/
5460{
5461 return (utab->lexlevel == functionScope);
5462}
5463
5464void
5465usymtab_replaceEntry (uentry s)
5466 /*@globals utab, globtab@*/
5467 /*@modifies utab, s@*/
5468{
5469 usymtab_replaceEntryAux (utab, s);
5470}
5471
5472bool
5473usymtab_matchForwardStruct (typeId u1, typeId u2)
5474 /*@globals globtab@*/
5475{
5476 uentry ue1 = usymtab_getTypeEntry (u1);
5477 uentry ue2 = usymtab_getTypeEntry (u2);
5478
5479 if (uentry_isAnyTag (ue2))
5480 {
5481 ctype reptype = uentry_getType (ue1);
5482
5483 if (ctype_isPointer (reptype))
5484 {
5485 ctype repbase = ctype_getBaseType (reptype);
5486
5487 if (ctype_isUA (repbase))
5488 {
5489 typeId rtuid = ctype_typeId (repbase);
5490
5491 if (u2 == rtuid) return TRUE;
5492
5493 if (typeId_isValid (rtuid))
5494 {
5495 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5496 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5497 }
5498 }
5499 }
5500 }
5501
5502 return FALSE;
5503}
5504
5505void usymtab_addGuards (guardSet guards)
5506 /*@modifies utab@*/
5507{
5508 utab->guards = guardSet_union (utab->guards, guards);
5509 }
5510
5511static bool usymtab_isGuardedAux (sRef s)
5512 /*@globals utab@*/
5513{
5514 usymtab tab = utab;
5515 sRef base = sRef_getRootBase (s);
5516 int lowlevel = paramsScope;
5517 int baselevel = sRef_lexLevel (base);
5518
5519 if (sRef_isCvar (base))
5520 {
5521 lowlevel = baselevel;
5522 if (lowlevel < paramsScope) lowlevel = paramsScope;
5523 }
5524
5525 while (tab->lexlevel >= lowlevel)
5526 {
5527 DPRINTF (("Is guarded? [%s] %s",
5528 guardSet_unparse (tab->guards),
5529 sRef_unparseFull (s)));
5530
5531 if (guardSet_isGuarded (tab->guards, s))
5532 {
5533 /*
5534 if (!sRef_definitelyNull (s))
5535 {
5536 sRef_setNotNull (s, fileloc_undefined);
5537 }
5538 */
5539 return TRUE;
5540 }
5541
5542 tab = usymtab_dropEnv (tab);
5543 }
5544
5545 return FALSE;
5546}
5547
5548void usymtab_unguard (sRef s) /*@modifies utab@*/
5549{
5550 usymtab tab = utab;
5551 sRef base = sRef_getRootBase (s);
5552 int lowlevel = paramsScope;
5553 int baselevel = sRef_lexLevel (base);
5554
5555 if (sRef_isCvar (base))
5556 {
5557 lowlevel = baselevel;
5558 if (lowlevel < paramsScope) lowlevel = paramsScope;
5559 }
5560
5561 while (tab->lexlevel >= lowlevel)
5562 {
5563 if (guardSet_isGuarded (tab->guards, s))
5564 {
5565 guardSet_delete (tab->guards, s);
5566 }
5567
5568 tab = usymtab_dropEnv (tab);
5569 }
5570}
5571
5572bool usymtab_isGuarded (sRef s)
5573{
5574 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5575 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5576}
5577
5578bool usymtab_isDefinitelyNull (sRef s)
5579{
5580 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5581}
5582
5583bool usymtab_isDefinitelyNullDeep (sRef s)
5584{
5585 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5586}
5587
5588static bool usymtab_isDefinitelyNullAux (sRef s)
5589 /*@globals utab@*/
5590{
5591 usymtab tab = utab;
5592 sRef base = sRef_getRootBase (s);
5593 int lowlevel = paramsScope;
5594
5595 if (sRef_isCvar (base))
5596 {
5597 lowlevel = sRef_lexLevel (base);
5598 if (lowlevel < paramsScope) lowlevel = paramsScope;
5599 }
5600
5601 while (tab->lexlevel >= lowlevel)
5602 {
5603 if (guardSet_mustBeNull (tab->guards, s))
5604 {
5605 return TRUE;
5606 }
5607
5608 while (tab->kind == US_CBRANCH)
5609 {
5610 tab = tab->env;
5611 }
5612
5613 llassert (usymtab_isDefined (tab));
5614
5615 if (tab->kind == US_FBRANCH)
5616 {
5617 tab = tab->env;
5618 llassert (tab->kind == US_TBRANCH);
5619 }
5620
5621 tab = tab->env;
5622 }
5623
5624 return FALSE;
5625}
5626
5627void
5628usymtab_printGuards ()
5629 /*@globals utab, globtab@*/
5630{
5631 usymtab ttab = utab;
5632
5633 while (ttab != globtab)
5634 {
5635 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5636 guardSet_unparse (ttab->guards)));
5637 ttab = ttab->env;
5638 }
5639}
5640
5641void
5642usymtab_displayAllUses ()
5643 /*@globals utab, globtab@*/
5644{
5645 usymtab copy;
5646
5647 /* only in top scope */
5648 llassert (utab == globtab);
5649
5650 /* need a copy, so order is not messed up by sort! */
5651 copy = usymtab_shallowCopy (globtab);
5652
5653 qsort (copy->entries, (size_t)copy->nentries,
5654 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5655
5656 usymtab_entries (copy, ue)
5657 {
5658 if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5659 {
5660 filelocList uses = uentry_getUses (ue);
5661 int size = filelocList_realSize (uses);
5662
5663 if (fileloc_isDefined (uentry_whereDefined (ue))
5664 && !fileloc_isLib (uentry_whereDefined (ue))
5665 && (size > 0))
5666 {
5667 llmsg (message ("%q (%q), %d use%&:\n %q",
5668 uentry_getName (ue),
5669 fileloc_unparse (uentry_whereDefined (ue)),
5670 size, filelocList_unparseUses (uses)));
5671 }
5672 }
5673 } end_usymtab_entries;
5674
5675 usymtab_shallowFree (copy);
5676}
5677
5678static /*@dependent@*/ /*@exposed@*/ usymtab
5679usymtab_getFileTab ()
5680 /*@globals filetab@*/
5681{
5682 llassert (filetab != NULL);
5683
5684 return filetab;
5685}
5686
5687/*@only@*/ cstring
5688usymtab_unparseStack ()
5689 /*@globals utab@*/
5690{
5691 return (usymtab_unparseStackTab (utab));
5692}
5693
5694static /*@only@*/ cstring
5695usymtab_unparseStackTab (usymtab t)
5696{
5697 bool firstOne = TRUE;
5698 cstring ret = cstring_makeLiteral ("[");
5699
5700 while (t != GLOBAL_ENV)
5701 {
5702 if (firstOne)
5703 {
5704 ret = message ("%q %q", ret, usymtab_typeName (t));
5705 firstOne = FALSE;
5706 }
5707 else
5708 {
5709 ret = message ("%q, %q", ret, usymtab_typeName (t));
5710 }
5711 t = t->env;
5712 }
5713
5714 ret = message ("%q ]", ret);
5715 return ret;
5716}
5717
5718static /*@only@*/ cstring
5719usymtab_typeName (/*@notnull@*/ usymtab t)
5720{
5721 switch (t->kind)
5722 {
5723 case US_GLOBAL: return cstring_makeLiteral ("global");
5724 case US_NORMAL: return cstring_makeLiteral ("normal");
5725 case US_TBRANCH: return cstring_makeLiteral ("true");
5726 case US_FBRANCH: return cstring_makeLiteral ("false");
5727 case US_CBRANCH: return cstring_makeLiteral ("case");
5728 case US_SWITCH: return cstring_makeLiteral ("switch");
5729 }
5730
5731 BADEXIT;
5732}
5733
5734void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5735 /*@modifies utab@*/
5736{
5737 if (!sRef_similar (s, al))
5738 {
5739 usymtab_addForceMustAlias (s, al);
5740 }
5741}
5742
5743/*
5744** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5745*/
5746
5747void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5748 /*@modifies utab@*/
5749{
5750 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5751 if (sRef_isMeaningful (s)
5752 && sRef_isMeaningful (al)
5753 && !(sRef_isConst (s) || sRef_isConst (al))
5754 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5755 {
5756 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5757 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5758
5759 /*
5760 ** for local variable, aliasing is symmetric
5761 */
5762
5763 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5764 {
5765 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5766 }
5767 }
5768 else
5769 {
5770 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5771 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5772 }
5773}
5774
5775void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5776 /*@modifies utab@*/
5777{
5778 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5779}
5780
5781void usymtab_clearAlias (sRef s)
5782 /*@modifies utab, s@*/
5783{
5784
5785 aliasTable_clearAliases (utab->aliases, s);
5786}
5787
5788sRefSet usymtab_allAliases (sRef s)
5789 /*@globals utab@*/
5790{
5791 if (sRef_isSomewhatMeaningful (s))
5792 {
5793 sRefSet ret;
5794
5795 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5796 aliasTable_canAlias (utab->aliases, s));
5797 return (ret);
5798 }
5799 else
5800 {
5801 DPRINTF (("NOT A MEANINGFUL SREF!"));
5802 return sRefSet_undefined;
5803 }
5804}
5805
5806/*@only@*/ sRefSet usymtab_canAlias (sRef s)
5807 /*@globals utab@*/
5808{
5809 if (sRef_isSomewhatMeaningful (s))
5810 {
5811 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5812 return res;
5813 }
5814
5815 return sRefSet_undefined;
5816}
5817
5818/*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5819 /*@globals utab@*/
5820{
5821 return (aliasTable_aliasedBy (utab->aliases, s));
5822}
5823
5824/*@only@*/ cstring usymtab_unparseAliases ()
5825 /*@globals utab@*/
5826{
5827 return (aliasTable_unparse (utab->aliases));
5828}
5829
5830/*
5831** Debugging routines:
5832** okay to leak storage here, only for debugging
5833*/
5834
5835/*@-mustfree@*/
5836
5837void
5838usymtab_printOut (void)
5839 /*@globals utab@*/
5840{
5841 int i;
5842 usymtab s = utab;
5843 int depth = 0;
5844 char *ind = mstring_copy (" ");
5845
5846 fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5847
5848 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5849 {
5850 cstring tname = usymtab_typeName (s);
5851
5852 if (depth < 5)
5853 {
5854 ind[depth * 3 + 1] = '\0';
5855 }
5856
5857 fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5858 cstring_toCharsSafe (tname));
5859
5860 cstring_free (tname);
5861
5862 for (i = 0; i < s->nentries; i++)
5863 {
5864 cstring us = uentry_unparseFull (s->entries[i]);
5865 fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5866 cstring_free (us);
5867 }
5868
5869 if (s->reftable != NULL && s->nentries > 0)
5870 {
5871 fprintf (g_warningstream, "\t<< Ref table >>\n");
5872
5873 for (i = 0; i < s->nentries; i++)
5874 {
5875 fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5876 s->reftable[i]->level,
5877 s->reftable[i]->index);
5878 }
5879 }
5880
5881 ind[depth * 3 + 1] = ' ';
5882 depth++;
5883 s = s->env;
5884 }
5885 fprintf (g_warningstream, "<<< end usymtab >>>\n");
5886 mstring_free (ind);
5887 return;
5888}
5889
5890void
5891usymtab_printTypes ()
5892 /*@globals globtab@*/
5893{
5894 usymtab_printAllAux (globtab);
5895}
5896
5897void
5898usymtab_printAll (void)
5899 /*@globals utab@*/
5900{
5901 usymtab_printAllAux (utab);
5902}
5903
5904static void
5905usymtab_printAllAux (usymtab s)
5906 /*@modifies g_warningstream@*/
5907{
5908 int i;
5909 int depth = 0;
5910 char *ind = mstring_copy (" ");
5911
5912 printf ("[[[ usymtab ]]]");
5913
5914 while (s != GLOBAL_ENV)
5915 {
5916 if (depth < 5)
5917 ind[depth * 3 + 1] = '\0';
5918
5919 if (s->env == GLOBAL_ENV)
5920 {
5921 int looplow;
5922
5923 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5924 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5925 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5926
5927 looplow = 0;
5928
5929 for (i = looplow; i < s->nentries; i++)
5930 {
5931 printf ("%s%3d. %s\n", ind, i,
5932 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5933 }
5934 }
5935 else
5936 {
5937 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5938 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5939 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5940
5941 for (i = 0; i < s->nentries; i++)
5942 {
5943 printf ("%s%3d %s\n", ind, i,
5944 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5945 }
5946 }
5947
5948 ind[depth * 3 + 1] = ' ';
5949 depth++;
5950 s = s->env;
5951 }
5952 printf ("----------\n");
5953}
5954
5955void
5956usymtab_printComplete ()
5957 /*@globals utab@*/
5958{
5959 int i;
5960 int depth = 0;
5961 char *ind = mstring_copy (" ");
5962 usymtab s = utab;
5963
5964 while (s != GLOBAL_ENV)
5965 {
5966 if (depth < 5)
5967 {
5968 ind[depth * 3 + 1] = '\0';
5969 }
5970
5971 if (s->env == GLOBAL_ENV)
5972 {
5973 int looplow;
5974
5975 printf ("level: %d\n", s->lexlevel);
5976
5977 looplow = 0;
5978
5979 for (i = looplow; i < s->nentries; i++)
5980 {
5981 printf ("%s%3d %s\n", ind, i,
5982 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5983 }
5984 }
5985 else
5986 {
5987 printf ("level: %d\n", s->lexlevel);
5988 for (i = 0; i < s->nentries; i++)
5989 {
5990 printf ("%s%3d %s\n", ind, i,
5991 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5992 }
5993 }
5994
5995 ind[depth * 3 + 1] = ' ';
5996 depth++;
5997 s = s->env;
5998 }
5999
6000 printf ("----------\n");
6001 mstring_free (ind);
6002}
6003
6004# ifdef S_SPLINT_S
6005static /*@only@*/ cstring /*@unused@*/
6006usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
6007{
6008 cstring c = message ("lexlevel: %d\n", s->lexlevel);
6009 int i;
6010
6011 for (i = 0; i < s->nentries; i++)
6012 {
6013 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
6014 }
6015
6016 c = message ("%q\n=========", c);
6017 return (c);
6018}
6019
6020static cstring /*@unused@*/ /*@only@*/
6021usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
6022{
6023 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
6024 bool_unparse (s->mustBreak),
6025 exitkind_unparse (s->exitCode));
6026 int i;
6027
6028 for (i = 0; i < s->nentries; i++)
6029 {
6030 sRef sr = uentry_getSref (s->entries[i]);
6031
6032 if (i == 0)
6033 {
6034 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
6035 sRef_isStateDefined (sr));
6036 }
6037 else
6038 {
6039 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
6040 sRef_isStateDefined (sr));
6041 }
6042
6043 }
6044
6045 return (c);
6046}
6047# endif
6048
6049void
6050usymtab_printLocal (void)
6051 /*@globals utab@*/
6052{
6053 int i;
6054 usymtab s = utab;
6055
6056 printf ("lexlevel: %d\n", s->lexlevel);
6057
6058 for (i = 0; i < s->nentries; i++)
6059 {
6060 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6061 }
6062
6063 while (s->lexlevel > 1)
6064 {
6065 s = s->env;
6066 }
6067
6068 llassert (usymtab_isDefined (s));
6069
6070 printf ("Params:\n");
6071
6072 for (i = 0; i < s->nentries; i++)
6073 {
6074 printf ("%d: %s\n", i,
6075 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6076 }
6077}
6078/*@=mustfree@*/
6079
6080static bool checkDistinctExternalName (uentry e)
6081 /*@globals globtab@*/
6082 /*@modifies *g_warningstream@*/
6083{
6084 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6085 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6086 bool gotone = FALSE;
6087 bool extras = FALSE;
6088 bool hasError = FALSE;
6089 cstring name = uentry_rawName (e);
6090 usymtab st = globtab;
6091
6092 if (checklen == 0)
6093 {
6094 ;
6095 }
6096 else
6097 {
6098 if (uentry_isAnyTag (e))
6099 {
6100 checklen++; /* the tag marker doesn't count */
6101 }
6102 }
6103
6104 usymtab_entries (st, oe)
6105 {
6106 if (uentry_sameObject (oe, e))
6107 {
6108 continue;
6109 }
6110
6111 if (checklen == 0)
6112 {
6113 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6114 {
6115 if (gotone)
6116 {
6117 extras = TRUE;
6118 break;
6119 }
6120
6121 if (optgenerror
6122 (FLG_DISTINCTEXTERNALNAMES,
6123 message
6124 ("External identifier %q is not distinguishable from %q "
6125 "because alphabetical case is ignored",
6126 uentry_getName (e),
6127 uentry_getName (oe)),
6128 uentry_whereLast (e)))
6129 {
6130 uentry_showWhereAny (oe);
6131 uentry_setHasNameError (oe);
6132 gotone = TRUE;
6133 }
6134 }
6135 }
6136 else
6137 {
6138 if (ignorecase)
6139 {
6140 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6141 name, checklen))
6142 {
6143 if (gotone)
6144 {
6145 extras = TRUE;
6146 break;
6147 }
6148
6149 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6150 {
6151 if (optgenerror
6152 (FLG_DISTINCTEXTERNALNAMES,
6153 /*@-sefparams@*/
6154 message
6155 ("External identifier %q is not distinguishable from %q "
6156 "in the first %d characters (%q)",
6157 uentry_getName (e),
6158 uentry_getName (oe),
6159 size_toInt (checklen),
6160 cstring_clip (uentry_getName (e), checklen)),
6161 /*@=sefparams@*/
6162 uentry_whereLast (e)))
6163 {
6164 uentry_showWhereAny (oe);
6165 uentry_setHasNameError (oe);
6166 gotone = TRUE;
6167 }
6168 }
6169 else
6170 {
6171 if (gotone)
6172 {
6173 extras = TRUE;
6174 break;
6175 }
6176
6177 if (optgenerror
6178 (FLG_DISTINCTEXTERNALNAMES,
6179 message
6180 ("External identifier %q is not distinguishable from %q "
6181 "in the first %d characters because alphabetical case "
6182 "is ignored",
6183 uentry_getName (e),
6184 uentry_getName (oe),
6185 size_toInt (checklen)),
6186 uentry_whereLast (e)))
6187 {
6188 uentry_showWhereAny (oe);
6189 uentry_setHasNameError (oe);
6190 gotone = TRUE;
6191 }
6192 }
6193 }
6194 }
6195 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6196 {
6197 if (gotone)
6198 {
6199 extras = TRUE;
6200 break;
6201 }
6202
6203 if (optgenerror
6204 (FLG_DISTINCTEXTERNALNAMES,
6205 /*@-sefparams@*/
6206 message
6207 ("External identifier %q is not distinguishable from %q "
6208 "in the first %d characters (%q)",
6209 uentry_getName (e),
6210 uentry_getName (oe),
6211 size_toInt (checklen),
6212 cstring_clip (uentry_getName (e), checklen)),
6213 /*@=sefparams@*/
6214 uentry_whereLast (e)))
6215 {
6216 uentry_showWhereAny (oe);
6217 uentry_setHasNameError (oe);
6218 gotone = TRUE;
6219 }
6220 }
6221 else
6222 {
6223 ; /* okay */
6224 }
6225 }
6226 } end_usymtab_entries ;
6227
6228 hasError = gotone;
6229
6230 if (extras)
6231 {
6232 llgenindentmsgnoloc
6233 (cstring_makeLiteral ("One or more additional "
6234 "indistinguishable external "
6235 "names not reported"));
6236 }
6237
6238 return hasError;
6239}
6240
6241static bool checkDistinctInternalName (uentry e)
6242 /*@globals utab@*/
6243 /*@modifies *g_warningstream@*/
6244{
6245 usymtab ttab = utab;
6246 cstring name = uentry_rawName (e);
6247 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6248 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6249 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6250
6251 if (uentry_isAnyTag (e) && (numchars != 0))
6252 {
6253 numchars++; /* the tag marker doesn't count */
6254 }
6255
6256 while (usymtab_isDefined (ttab))
6257 {
6258 usymtab_entries (ttab, oe)
6259 {
6260 if (uentry_sameObject (oe, e))
6261 {
6262 /*@innercontinue@*/ continue;
6263 }
6264
6265 switch (cstring_genericEqual
6266 (name, uentry_rawName (oe),
6267 numchars, caseinsensitive, lookalike))
6268 {
6269 case CGE_DISTINCT: /* okay */
6270 /*@switchbreak@*/
6271 break;
6272 case CGE_SAME:
6273 if (cstring_equal (name, uentry_rawName (oe)))
6274 {
6275 ; /* got a shadow error */
6276 }
6277 else
6278 {
6279 if (optgenerror
6280 (FLG_DISTINCTINTERNALNAMES,
6281 /*@-sefparams@*/
6282 message
6283 ("Internal identifier %q is not distinguishable from %q "
6284 "in the first %d characters (%q)",
6285 uentry_getName (e),
6286 uentry_getName (oe),
6287 size_toInt (numchars),
6288 cstring_clip (uentry_getName (e), numchars)),
6289 /*@=sefparams@*/
6290 uentry_whereLast (e)))
6291 {
6292 uentry_showWhereAny (oe);
6293 uentry_setHasNameError (oe);
6294 return TRUE;
6295 }
6296 }
6297 /*@switchbreak@*/
6298 break;
6299 case CGE_CASE:
6300 if (numchars == 0 || (cstring_length (name) <= numchars))
6301 {
6302 if (optgenerror
6303 (FLG_DISTINCTINTERNALNAMES,
6304 message
6305 ("Internal identifier %q is not distinguishable from %q "
6306 "without case sensitivity",
6307 uentry_getName (e),
6308 uentry_getName (oe)),
6309 uentry_whereLast (e)))
6310 {
6311 uentry_showWhereAny (oe);
6312 uentry_setHasNameError (oe);
6313 return TRUE;
6314 }
6315 }
6316 else
6317 {
6318 if (optgenerror
6319 (FLG_DISTINCTINTERNALNAMES,
6320 message
6321 ("Internal identifier %q is not distinguishable from %q "
6322 "in the first %d characters without case sensitivity",
6323 uentry_getName (e),
6324 uentry_getName (oe),
6325 size_toInt (numchars)),
6326 uentry_whereLast (e)))
6327 {
6328 uentry_showWhereAny (oe);
6329 uentry_setHasNameError (oe);
6330 return TRUE;
6331 }
6332 }
6333 /*@switchbreak@*/
6334 break;
6335 case CGE_LOOKALIKE:
6336 if (numchars == 0
6337 || (cstring_length (name) <= numchars))
6338 {
6339 if (optgenerror
6340 (FLG_DISTINCTINTERNALNAMES,
6341 message
6342 ("Internal identifier %q is not distinguishable from %q "
6343 "except by lookalike characters",
6344 uentry_getName (e),
6345 uentry_getName (oe)),
6346 uentry_whereLast (e)))
6347 {
6348 uentry_showWhereAny (oe);
6349 uentry_setHasNameError (oe);
6350 return TRUE;
6351 }
6352 }
6353 else
6354 {
6355 if (optgenerror
6356 (FLG_DISTINCTINTERNALNAMES,
6357 message
6358 ("Internal identifier %q is not distinguishable from %q "
6359 "in the first %d characters except by lookalike characters",
6360 uentry_getName (e),
6361 uentry_getName (oe),
6362 size_toInt (numchars)),
6363 uentry_whereLast (e)))
6364 {
6365 uentry_showWhereAny (oe);
6366 uentry_setHasNameError (oe);
6367 return TRUE;
6368 }
6369 }
6370 }
6371 } end_usymtab_entries ;
6372
6373 ttab = ttab->env;
6374 }
6375
6376 return FALSE;
6377}
6378
6379void usymtab_checkDistinctName (uentry e, int scope)
6380 /*@globals utab, globtab@*/
6381{
6382 bool hasError = FALSE;
6383 fileloc where = uentry_whereLast (e);
6384
6385 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6386 {
6387 if (scope == globScope)
6388 {
6389 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6390 {
6391 hasError = checkDistinctExternalName (e);
6392 }
6393 }
6394
6395 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6396 {
6397 hasError = checkDistinctInternalName (e);
6398 }
6399 }
6400
6401 if (hasError)
6402 {
6403 uentry_setHasNameError (e);
6404 }
6405}
6406
6407/*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6408{
6409 uentry ue;
6410
6411 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6412 llassert (uentry_isValid (ue));
6413
6414 return uentry_getSref (ue);
6415}
6416
6417
6418# ifdef DEBUGSPLINT
6419/*
6420** For debugging only
6421*/
6422
6423void
6424usymtab_checkAllValid () /*@globals utab@*/
6425{
6426 usymtab tab = utab;
6427
6428 while (tab != GLOBAL_ENV)
6429 {
6430 int i;
6431
6432 for (i = 0; i < utab->nentries; i++)
6433 {
6434 uentry e = utab->entries[i];
6435
6436 uentry_checkValid (e);
6437 }
6438
6439 aliasTable_checkValid (tab->aliases);
6440 tab = tab->env;
6441 }
6442}
6443# endif
6444
6445
6446
6447
6448
6449
This page took 0.138326 seconds and 5 git commands to generate.