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