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