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