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