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