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