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