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