]> andersk Git - splint.git/blame - src/usymtab.c
Fixed line numbering when multi-line macro parameters are used.
[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 {
2908 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2909 }
2910 }
2911 }
2912 else
2913 {
2914 }
2915
2916 ue = usymtab_getRefTab (ftab, level, index);
2917
2918 if (!uentry_isLset (ue))
2919 {
2920 sRef sr = uentry_getSref (ue);
2921
2922
2923 if (!trueGuard) /* yikes! forgot the ! */
2924 {
2925 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2926 }
2927 else
2928 {
2929
2930 if (!guardSet_isGuarded (ftab->guards, el)
2931 && !sRef_isNotNull (sr))
2932 {
2933 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2934 }
2935 }
2936 }
2937 else
2938 {
28bf4b0b 2939 ;
2940 }
2941 }
2942}
616915dd 2943
2944void
2945usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2946 bool isOpt, clause cl)
2947 /*@modifies utab@*/
2948{
2949 int i = 0;
2950 usymtab ftab = utab;
2951 usymtab ttab = utab->env;
2952
2953 fileloc loc;
2954 usymtab env;
2955 guardSet guards = exprNode_getGuards (pred);
2956 sRefSet tguards = guardSet_getTrueGuards (guards);
2957 sRefSet fguards = guardSet_getFalseGuards (guards);
2958 bool mustReturnT = exprNode_mustEscape (tbranch);
2959 bool mustReturnF = exprNode_mustEscape (fbranch);
28bf4b0b 2960
2961 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
2962 bool_unparse (mustReturnT),
2963 bool_unparse (mustReturnF)));
2964
616915dd 2965 if (exprNode_isDefined (fbranch))
2966 {
2967 loc = exprNode_loc (fbranch);
2968 }
2969 else
2970 {
2971 loc = exprNode_loc (tbranch);
2972 }
2973
2974 llassert (usymtab_isDefined (ttab));
2975
2976 env = ttab->env;
2977
2978 llassert (usymtab_isDefined (env));
2979 llassert (ftab->kind == US_FBRANCH);
2980 llassert (ttab->kind == US_TBRANCH);
2981
2982 /*
2983 ** For each element that is true guarded (i.e., if (x != NULL))
2984 ** make x = null in false branch,
2985 ** and x = notnull in true branch.
2986 ** unless x was set locally in that branch.
2987 ** For each element that is false guarded (x == NULL)
2988 ** make x = null in true, notnull in false.
2989 **
2990 ** For each element that is either guarded (pred(x))
2991 **
2992 */
2993
2994 sRefSet_allElements (tguards, el)
2995 {
2996 updateNullState (el, ttab, ftab, TRUE);
2997 } end_sRefSet_allElements;
2998
2999 sRefSet_allElements (fguards, el)
3000 {
3001 updateNullState (el, ttab, ftab, FALSE);
3002 } end_sRefSet_allElements;
3003
3004 /*
3005 **
3006 ** if an entry is in both true and false, merge the entries,
3007 ** then replace original with new state.
3008 **
3009 ** if an entry is in one table, merge it with the original.
3010 */
28bf4b0b 3011
3012 DPRINTF (("ftab: %d", ftab->nentries));
3013
616915dd 3014 for (i = 0; i < ftab->nentries; i++)
3015 {
3016 uentry fthis = ftab->entries[i];
3017 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3018 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3019
28bf4b0b 3020 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3021
616915dd 3022 if (uentry_isUndefined (old))
3023 {
3024 /* possible entry was added as an undefined id */
28bf4b0b 3025 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
616915dd 3026 continue;
3027 }
3028
3029 if (tindex != NOT_FOUND)
3030 {
3031 uentry tthis = ttab->entries[tindex];
28bf4b0b 3032
616915dd 3033 /* note that is this is in a nested branch,
3034 it may create a "new" old entry. */
3035
3036 if (!mustReturnF)
3037 {
3038 if (!mustReturnT)
3039 {
616915dd 3040 uentry_mergeState (fthis, tthis, loc,
3041 mustReturnT, FALSE, FALSE, cl);
3042 }
3043 else
3044 {
3045 uentry_mergeUses (fthis, tthis);
3046 }
3047
3048 uentry_setState (old, fthis);
3049
3050 /*@-mustfree@*/
3051 }
3052 /*@=mustfree@*/
3053 else
3054 {
3055 uentry_setState (old, tthis);
3056 uentry_mergeState (old, fthis, loc, mustReturnF,
3057 TRUE, FALSE, cl);
3058 }
3059
3060 ttab->entries[tindex] = uentry_undefined;
3061 uentry_free (tthis);
3062 }
3063 else
3064 {
3065 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3066 }
3067 }
3068
3069 for (i = 0; i < ttab->nentries; i++)
3070 {
3071 uentry current = ttab->entries[i];
3072
28bf4b0b 3073 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3074
616915dd 3075 if (!uentry_isUndefined (current))
3076 {
3077 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3078
28bf4b0b 3079 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3080
3081 if (uentry_isUndefined (old))
3082 {
3083 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3084 continue;
3085 }
3086
616915dd 3087 if (mustReturnF)
3088 {
3089 uentry_mergeUses (current, old);
3090 uentry_setState (old, current);
3091 }
3092 else
3093 {
3094 /*
28bf4b0b 3095 ** Assumes false branch is a fall-through if
616915dd 3096 ** fbranch is not defined. This is true, unless
3097 ** where was some greivous error in processing
3098 ** the else branch of an if-then, in which case
3099 ** this is probably the right thing to do anyway.
3100 */
3101
3102 uentry_mergeState (old, current, loc, mustReturnT,
3103 FALSE, isOpt, cl);
3104 }
28bf4b0b 3105
3106 DPRINTF (("==> %s", uentry_unparseFull (old)));
616915dd 3107 }
3108 }
616915dd 3109
3110 /*
3111 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3112 ** if they are present.
3113 */
3114
3115 llassert (NOALIAS (env->aliases, ttab->aliases));
3116 llassert (NOALIAS (env->aliases, ftab->aliases));
3117
3118 aliasTable_free (env->aliases);
3119
3120 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3121 ftab->aliases, env->lexlevel);
3122
3123 aliasTable_fixSrefs (env->aliases);
28bf4b0b 3124
3125 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
616915dd 3126
3127 /* exit true and false scopes */
3128 usymtab_quietPlainExitScope ();
3129 usymtab_quietPlainExitScope ();
3130
3131 if (mustReturnT)
3132 {
3133 utab->guards = guardSet_levelUnionFree
3134 (utab->guards,
3135 guardSet_invert (exprNode_getGuards (pred)),
3136 utab->lexlevel);
3137 }
3138
3139 if (mustReturnF)
3140 {
3141 utab->guards = guardSet_levelUnion (utab->guards,
3142 exprNode_getGuards (pred),
3143 utab->lexlevel);
3144 }
3145
3146 DPRINTF (("Here."));
3147}
3148
3149static void usymtab_fixCases (void) /*@modifies utab@*/ {
3150 while (utab->kind == US_CBRANCH)
3151 {
3152 usymtab_quietPlainExitScope ();
3153 }
3154
3155 llassert (utab->kind != US_CBRANCH);
3156}
3157
3158void
3159usymtab_altBranch (/*@only@*/ guardSet guards)
3160 /*@modifies utab@*/
3161{
28bf4b0b 3162 usymtab t;
616915dd 3163 usymtab parent = utab->env;
3164
28bf4b0b 3165 t = usymtab_create (US_FBRANCH, utab, FALSE);
3166
616915dd 3167 /*
3168 ** If we are in a case, need to close it. The C syntax
3169 ** is very liberal, so this kludge is necessary.
3170 */
3171
3172 usymtab_fixCases ();
3173
3174 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
28bf4b0b 3175
616915dd 3176 llassert (utab->kind == US_TBRANCH);
3177 llassert (parent != GLOBAL_ENV);
28bf4b0b 3178
616915dd 3179 guardSet_free (t->guards);
3180 t->guards = guards;
28bf4b0b 3181
616915dd 3182 aliasTable_free (t->aliases);
3183 t->aliases = aliasTable_copy (parent->aliases);
28bf4b0b 3184
616915dd 3185 utab = t;
3186}
3187
3188void
3189usymtab_allDefined (void)
3190 /*@globals utab, globtab@*/
3191{
3192 int i;
3193
3194 llassert (utab == globtab);
3195
3196 for (i = 0; i < utab->nentries; i++)
3197 {
3198 uentry e = utab->entries[i];
3199
3200 if (uentry_isPriv (e))
3201 {
3202 ; /* no need to define it */
3203 }
3204 else
3205 {
3206 if (context_getFlag (FLG_SPECUNDECL))
3207 {
3208 fileloc sloc = uentry_whereSpecified (e);
3209 fileloc dloc = uentry_whereDeclared (e);
3210
3211 if (fileloc_isDefined (sloc)
3212 && !uentry_isFakeTag (e)
3213 && !fileloc_isDefined (dloc))
3214 {
3215 voptgenerror
3216 (FLG_SPECUNDECL,
3217 message ("%s %q specified but not declared",
3218 ekind_capName (uentry_getKind (e)),
3219 uentry_getName (e)),
3220 sloc);
3221 }
3222 }
3223
3224 if (!uentry_isCodeDefined (e))
3225 {
3226 fileloc dloc = uentry_whereDeclared (e);
3227
28bf4b0b 3228 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
616915dd 3229 {
3230 ;
3231 }
3232 else if (fileloc_isDefined (dloc))
3233 {
3234 if (!uentry_isAnyTag (e))
3235 {
3236 if (fileloc_isUser (dloc))
3237 {
3238 voptgenerror
3239 (FLG_DECLUNDEF,
3240 message ("%s %q declared but not defined",
3241 ekind_capName (uentry_getKind (e)),
3242 uentry_getName (e)),
3243 dloc);
efd360a3 3244 DPRINTF (("decl: %s", uentry_unparseFull (e)));
616915dd 3245 }
3246 }
3247 }
3248 else
3249 {
3250 fileloc sloc = uentry_whereSpecified (e);
3251
3252 if (fileloc_isDefined (sloc)
3253 && !fileloc_isImport (sloc)
3254 && !fileloc_isLib (sloc)
3255 && !fileloc_isPreproc (sloc)
3256 && !uentry_isFakeTag (e))
3257 {
3258 if (uentry_isVariable (e) || uentry_isFunction (e))
3259 {
3260 voptgenerror
3261 (FLG_SPECUNDEF,
3262 message ("%s %q specified but not declared or defined",
3263 ekind_capName (uentry_getKind (e)),
3264 uentry_getName (e)),
3265 sloc);
3266 }
3267 else
3268 {
3269 voptgenerror
3270 (FLG_SPECUNDEF,
3271 message ("%s %q specified but not defined",
3272 ekind_capName (uentry_getKind (e)),
3273 uentry_getName (e)),
3274 sloc);
3275 }
3276 }
3277 }
3278 }
3279 }
3280 }
3281}
3282
3283void usymtab_exportHeader (void)
3284 /*@globals utab@*/
3285{
3286 int i;
3287
3288 for (i = 0; i < utab->nentries; i++)
3289 {
3290 uentry ce = utab->entries[i];
3291
3292 if (!uentry_isDatatype (ce)
3293 && !uentry_isAnyTag (ce)
3294 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3295 && !uentry_isExternal (ce)
3296 && !uentry_isForward (ce))
3297 {
3298 fileloc fwhere = uentry_whereDeclared (ce);
3299
3300 if (fileloc_isUndefined (fwhere)
3301 && uentry_isFunction (ce))
3302 {
3303 fwhere = uentry_whereDefined (ce);
3304 }
3305
3306 if (fileloc_isDefined (fwhere)
3307 && !fileloc_isHeader (fwhere)
28bf4b0b 3308 && !fileloc_isXHFile (fwhere)
616915dd 3309 && !(fileloc_isSpecialFile (fwhere)
3310 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3311 {
3312 if (uentry_isVariable (ce))
3313 {
3314 if (optgenerror
3315 (FLG_EXPORTHEADERVAR,
3316 message ("%s %q exported but not declared in header file",
3317 ekind_capName (uentry_getKind (ce)),
3318 uentry_getName (ce)),
3319 fwhere))
3320 {
3321 uentry_showDefSpecInfo (ce, fwhere);
3322 }
3323 }
3324 else
3325 {
3326 if (!uentry_isIter (ce)
3327 && !uentry_isEndIter (ce)
3328 && !uentry_isExpandedMacro (ce))
3329 {
3330 if (uentry_isFunction (ce)
3331 && cstring_equalLit (uentry_rawName (ce), "main"))
3332 {
3333 ; /* no error for main */
3334 }
3335 else
3336 {
3337 if (optgenerror
3338 (FLG_EXPORTHEADER,
3339 message ("%s %q exported but not declared "
3340 "in header file",
3341 ekind_capName (uentry_getKind (ce)),
3342 uentry_getName (ce)),
3343 fwhere))
3344 {
3345 uentry_showDefSpecInfo (ce, fwhere);
3346 }
3347 }
3348 }
3349 }
3350 }
3351 }
3352 }
3353}
3354
3355void usymtab_exportLocal (void)
3356 /*@globals utab@*/
3357{
3358 int i;
616915dd 3359
3360 for (i = 0; i < utab->nentries; i++)
3361 {
3362 uentry ce = utab->entries[i];
616915dd 3363
3364 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3365 && !uentry_isEitherConstant (ce)
3366 && !uentry_isIter (ce)
3367 && !uentry_isEndIter (ce)
3368 && !uentry_isExpandedMacro (ce)
3369 && uentry_isUsed (ce))
3370 {
3371 /* check static uses */
3372 filelocList fuses = uentry_getUses (ce);
3373 fileloc mod = uentry_whereDefined (ce);
3374 bool ok = filelocList_isEmpty (fuses);
3375 fileloc fwhere = uentry_whereDeclared (ce);
3376
3377 if (fileloc_isSpecialFile (fwhere)
3378 && !context_getFlag (FLG_UNUSEDSPECIAL))
3379 {
3380 ok = TRUE; /* no errors for special files */
3381 }
3382 else
3383 {
3384 filelocList_elements (fuses, uloc)
3385 {
3386 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3387 {
3388 ok = TRUE;
3389 /*@innerbreak@*/ break;
3390 }
3391 } end_filelocList_elements;
3392 }
3393
3394 if (!ok)
3395 {
3396 if (optgenerror
3397 (FLG_EXPORTLOCAL,
3398 message ("%s exported but not used outside %s: %q",
3399 ekind_capName (uentry_getKind (ce)),
3400 fileloc_getBase (mod),
3401 uentry_getName (ce)),
3402 fwhere))
3403 {
3404 uentry_showDefSpecInfo (ce, fwhere);
3405 }
3406 }
3407 }
3408 }
3409}
3410
3411void
3412usymtab_allUsed (void)
3413 /*@globals utab@*/
3414{
3415 int i;
3416 bool isFileStatic = usymtab_inFileScope ();
3417 cstring last_file = cstring_undefined;
3418
3419 for (i = 0; i < utab->nentries; i++)
3420 {
3421 bool hasError = FALSE;
3422 uentry ce = utab->entries[i];
3423 fileloc fwhere = uentry_whereDeclared (ce);
3424
3425 if (fileloc_isUndefined (fwhere))
3426 {
3427 fwhere = uentry_whereDefined (ce);
3428 }
3429
3430 if (fileloc_isInvalid (fwhere)
3431 || fileloc_isLib (fwhere)
3432 || fileloc_isBuiltin (fwhere)
3433 || ((fileloc_isSpecialFile (fwhere)
3434 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3435 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3436 {
3437 ;
3438 }
3439 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3440 {
3441 cstring fname = fileloc_filename (fwhere);
3442
3443 if (cstring_isUndefined (last_file))
3444 {
3445 last_file = fname;
3446 }
3447 else if (cstring_equal (fname, last_file))
3448 {
3449 }
3450 else
3451 {
3452 cleanupMessages ();
3453 last_file = fname;
3454 }
3455
3456 if (uentry_isParam (ce))
3457 {
3458 if (context_inMacro ())
3459 {
3460 sRef cref = uentry_getSref (ce);
3461
3462 if (uentry_isYield (ce))
3463 {
3464 ; /* no checks (for now) */
3465 }
3466 else if (sRef_isSafe (cref))
3467 {
3468 ; /* no error */
3469 }
3470 else
3471 {
3472 if (uentry_hasRealName (ce))
3473 {
3474 hasError =
3475 optgenerror (FLG_MACROPARAMS,
3476 message ("Macro parameter %q not used",
3477 uentry_getName (ce)),
3478 fwhere);
3479 }
3480 }
3481 }
3482 else
3483 {
3484 if (cstring_equalFree (uentry_getName (ce),
3485 cstring_makeLiteral ("...")))
3486 {
3487 ;
3488 }
3489 else
3490 {
3491 hasError = optgenerror (FLG_PARAMUNUSED,
3492 message ("Parameter %q not used",
3493 uentry_getName (ce)),
3494 fwhere);
3495 }
3496 }
3497 } /* isParam */
3498 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3499 {
3500 if (fileloc_isUser (fwhere))
3501 {
3502 hasError = optgenerror
3503 (FLG_FUNCUNUSED,
3504 message ("%q %q declared but not used",
3505 cstring_makeLiteral
3506 (uentry_isIter (ce) ? "Iterator"
3507 : (isFileStatic ? "File static function" : "Function")),
3508 uentry_getName (ce)),
3509 fwhere);
3510 }
3511 }
3512 else if (uentry_isEndIter (ce))
3513 {
3514 ; /* no error (already reported for iter */
3515 }
3516 else if (uentry_isEnumConstant (ce))
3517 {
3518 if (fileloc_isUser (fwhere))
3519 {
3520 hasError = optgenerror
3521 (FLG_ENUMMEMUNUSED,
3522 message ("Enum member %q not used",
3523 uentry_getName (ce)),
3524 fwhere);
3525 }
3526 }
3527 else if (uentry_isConstant (ce))
3528 {
3529 if (fileloc_isUser (fwhere))
3530 {
3531 hasError = optgenerror
3532 (FLG_CONSTUNUSED,
3533 message ("Constant %q declared but not used",
3534 uentry_getName (ce)),
3535 fwhere);
3536 }
3537 }
3538 else if (uentry_isDatatype (ce))
3539 {
3540 if (fileloc_isUser (fwhere))
3541 {
3542 hasError = optgenerror
3543 (FLG_TYPEUNUSED,
3544 message ("Type %q declared but not used",
3545 uentry_getName (ce)),
3546 fwhere);
3547 }
3548 }
3549 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3550 { /* errors for ref params will be reported in the next scope */
3551 llassertprint (uentry_isVar (ce),
3552 ("ce: %s", uentry_unparseFull (ce)));
3553
3554 if (ctype_isFunction (uentry_getType (ce)))
3555 {
3556 if (fileloc_isUser (fwhere))
3557 {
3558 hasError = optgenerror
3559 (FLG_FUNCUNUSED,
3560 message ("%q %q declared but not used",
3561 cstring_makeLiteral
3562 (isFileStatic ? "File static function"
3563 : "Function"),
3564 uentry_getName (ce)),
3565 fwhere);
3566 }
3567 }
3568 else
3569 {
3570 if (fileloc_isUser (fwhere))
3571 {
3572
3573
3574 hasError = optgenerror
3575 (FLG_VARUNUSED,
3576 message ("%q %q declared but not used",
3577 cstring_makeLiteral
3578 (isFileStatic ? "File static variable"
3579 : "Variable"),
3580 uentry_getName (ce)),
3581 fwhere);
3582 }
3583 }
3584 }
3585 else
3586 {
3587 ; /* no errors */
3588 }
3589 } /* unused */
28bf4b0b 3590 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
616915dd 3591 { /* check all fields */
3592 ctype ct = uentry_getRealType (ce);
3593
3594
3595 while (ctype_isAP (ct))
3596 {
3597 ct = ctype_getBaseType (ct);
3598 }
3599
616915dd 3600 if (ctype_isSU (ct))
3601 {
3602 uentryList fields = ctype_getFields (ct);
3603
3604 uentryList_elements (fields, field)
3605 {
3606 if (!uentry_isUsed (field))
3607 {
3608 if (uentry_hasName (ce))
3609 {
3610 hasError |= optgenerror
3611 (FLG_FIELDUNUSED,
3612 message ("Field %q of %s %q declared but not used",
3613 uentry_getName (field),
3614 cstring_makeLiteralTemp
3615 (ctype_isStruct (ct) ? "structure" : "union"),
3616 uentry_getName (ce)),
3617 uentry_whereEarliest (field));
3618 }
3619 else
3620 {
28bf4b0b 3621 /*
3622 ** evans 2001-06-08
3623 ** Can't report these errors for unnamed structs.
3624 ** No way to tell when there are multiple consistent
3625 ** unnamed structure types. (Could go through table
3626 ** and mark them all unused...)
3627
616915dd 3628 hasError |= optgenerror
3629 (FLG_FIELDUNUSED,
3630 message ("Field %q of unnamed %s declared but not used",
3631 uentry_getName (field),
3632 cstring_makeLiteralTemp
3633 (ctype_isStruct (ct) ? "structure" : "union")),
3634 uentry_whereEarliest (field));
28bf4b0b 3635
3636 */
616915dd 3637 }
3638
3639 uentry_setUsed (field, fileloc_undefined);
3640 }
3641 } end_uentryList_elements;
3642 }
3643 }
3644 else
3645 {
3646 ; /* no errors */
3647 }
3648
3649 if (hasError)
3650 {
3651 if (uentry_isParam (ce) && context_inMacro ())
3652 {
3653 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3654 {
3655 uentry_showWhereSpecified (ce);
3656 }
3657 }
3658 else
3659 {
3660 uentry_showDefSpecInfo (ce, fwhere);
3661 }
3662
3663 uentry_setUsed (ce, fileloc_undefined);
3664 }
3665 }
3666}
3667
3668static void
3669checkGlobalReturn (uentry glob, sRef orig)
3670{
3671 sRef sr = uentry_getSref (glob);
3672
b7b694d6 3673 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
28bf4b0b 3674 uentry_unparseFull (glob),
3675 sRef_unparseFull (orig),
3676 sRef_unparseFull (sr)));
3677
3678 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3679
616915dd 3680 if (context_getFlag (FLG_GLOBSTATE))
3681 {
28bf4b0b 3682 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3683
616915dd 3684 if (sRef_isKilledGlob (orig))
3685 {
3686 if (sRef_isStateUndefined (sr)
3687 || sRef_isUnuseable (sr)
3688 || sRef_isStateUnknown (sr)
3689 || sRef_isDead (sr))
3690 {
3691 ;
3692 }
3693 else
3694 {
3695 ctype ct = ctype_realType (uentry_getType (glob));
3696
2e127cb8 3697 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3698
616915dd 3699 if (ctype_isVisiblySharable (ct))
3700 {
3701 if (optgenerror
3702 (FLG_GLOBSTATE,
3703 message
28bf4b0b 3704 ("Killed global %q (type %s) not released before return",
3705 uentry_getName (glob),
3706 ctype_unparse (ct)),
616915dd 3707 g_currentloc))
3708 {
3709 sRef_showStateInfo (sr);
28bf4b0b 3710 }
616915dd 3711 }
3712 else
3713 {
28bf4b0b 3714 sRef_protectDerivs ();
2e127cb8 3715 (void) transferChecks_globalDestroyed (sr, g_currentloc);
616915dd 3716 sRef_clearProtectDerivs ();
3717 }
3718 }
3719 }
3720 else
3721 {
3722 if (sRef_isStateUndefined (sr))
3723 {
3724 if (optgenerror (FLG_GLOBSTATE,
3725 message
3726 ("Function returns with global %q undefined",
3727 uentry_getName (glob)),
3728 g_currentloc))
3729 {
3730 sRef_showStateInfo (sr);
3731 }
3732 }
3733 else
3734 {
7ebcc5bb 3735 if (sRef_isDead (sr) || sRef_isKept (sr))
616915dd 3736 {
3737 if (optgenerror
3738 (FLG_GLOBSTATE,
3739 message ("Function returns with global %q "
7ebcc5bb 3740 "referencing %s storage",
3741 uentry_getName (glob),
3742 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
616915dd 3743 g_currentloc))
3744 {
7ebcc5bb 3745 if (sRef_isKept (sr))
3746 {
3747 sRef_showAliasInfo (sr);
3748 }
3749 else
3750 {
3751 sRef_showStateInfo (sr);
3752 }
3753
616915dd 3754 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3755 }
3756 }
3757
28bf4b0b 3758 if (ctype_isRealPointer (uentry_getType (glob))
3759 && sRef_possiblyNull (sr)
3760 && !uentry_possiblyNull (glob))
616915dd 3761 {
3762 if (optgenerror
3763 (FLG_GLOBSTATE,
3764 message ("Function returns with non-null global %q "
3765 "referencing null storage",
3766 uentry_getName (glob)),
3767 g_currentloc))
3768 {
3769 sRef_showNullInfo (sr);
3770 }
3771 }
3772 else
3773 {
2e127cb8 3774 transferChecks_globalReturn (glob);
616915dd 3775 }
3776 }
3777 }
3778 }
3779}
3780
3781/*
3782** remember: check alias globals
3783*/
3784
3785void usymtab_checkFinalScope (bool isReturn)
3786 /*@globals utab@*/
3787{
2e127cb8 3788 bool mustFree = context_getFlag (FLG_MUSTFREEONLY) || context_getFlag (FLG_MUSTFREEFRESH); /*@i423 remove this mustFree */
616915dd 3789 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3790 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3791 sRefSet checked = sRefSet_new ();
3792 usymtab stab = utab;
3793 int i;
3794
3795 /*
3796 ** need to check all scopes out to function parameters.
3797 */
3798
3799 do
3800 {
3801 for (i = 0; i < stab->nentries; i++)
3802 {
3803 uentry ce = stab->entries[i];
3804 sRef sr = uentry_getSref (ce);
3805 sRef rb = sRef_getRootBase (sr);
28bf4b0b 3806 valueTable tvalues;
616915dd 3807
28bf4b0b 3808 /*
3809 ** Shouldn't check if shadow checked in deeper scope:
3810 */
3811
3812 if (stab != utab)
3813 {
3814 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3815
3816 if (!uentry_sameObject (ce, oue))
3817 {
3818 DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce),
3819 uentry_unparseFull (oue)));
3820 /*@i32 what if it is one an alternate branch? */
3821 /*@innercontinue@*/ continue;
3822 }
3823 }
3e3ec469 3824
28bf4b0b 3825 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3826
616915dd 3827 if (ctype_isFunction (uentry_getType (ce)))
3828 {
3829 /*@innercontinue@*/ continue;
3830 }
3831
28bf4b0b 3832 if (uentry_isAnyParam (ce)
3833 || uentry_isRefParam (ce)
3834 || sRef_isFileOrGlobalScope (rb))
3835 {
3836 /* Don't do the loseref check...but should check state! */
3e3ec469 3837 DPRINTF (("Skipping check 1"));
28bf4b0b 3838 }
3839 else if (sRef_isDefinitelyNull (sr)
3840 || usymtab_isDefinitelyNull (sr))
3841 {
3842 /*
3843 ** No state reference errors for definitely null references.
3844 */
3e3ec469 3845
3846 DPRINTF (("Skipping check 2"));
28bf4b0b 3847 }
3848 else
3849 {
3850 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3851 sRef_unparseFull (sr)));
3852
3853 tvalues = sRef_getValueTable (sr);
3854
3855 valueTable_elements (tvalues, fkey, fval) {
3856 metaStateInfo minfo;
3857 cstring msg = cstring_undefined;
3858 int nval;
3859
3860 minfo = context_lookupMetaStateInfo (fkey);
3861 llassert (metaStateInfo_isDefined (minfo));
3862
15b3d2b2 3863 if (stateValue_isError (fval)
3864 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
28bf4b0b 3865 {
3e3ec469 3866 DPRINTF (("Skipping check 3"));
28bf4b0b 3867 }
3868 else
3869 {
3870 DPRINTF (("Check: %s / %s / %s", fkey,
3871 metaStateInfo_unparse (minfo),
3872 stateValue_unparse (fval)));
3873
3874 minfo = context_lookupMetaStateInfo (fkey);
3875
3876 nval = stateCombinationTable_lookupLoseReference
3877 (metaStateInfo_getTransferTable (minfo),
3878 stateValue_getValue (fval), &msg);
3879
3880 if (cstring_isDefined (msg))
3881 {
3882 /*@i32 print extra info for assignments@*/
3883 DPRINTF (("From: %s", sRef_unparseFull (sr)));
3884 DPRINTF (("Null? %s / %s",
3885 bool_unparse (sRef_isDefinitelyNull (sr)),
3886 bool_unparse (usymtab_isGuarded (sr))));
3887
3888 if (optgenerror
3889 (FLG_STATETRANSFER,
3890 message
2c88d156 3891 ("%s loses reference %q in invalid state %q (%s)",
28bf4b0b 3892 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3893 uentry_getName (ce),
2c88d156 3894 stateValue_unparseValue (fval, minfo),
28bf4b0b 3895 msg),
3896 g_currentloc))
3897 {
3898 stateValue_show (fval, minfo);
3899 }
3900 else
3901 {
3902 DPRINTF (("Suppressed transfer error: %s", msg));
3903 }
3904 }
3905 }
3906 } end_valueTable_elements;
3907 }
3908
3e3ec469 3909 DPRINTF (("Here 1"));
3910
616915dd 3911 if (mustFree)
3912 {
3e3ec469 3913 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
28bf4b0b 3914
3915 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
616915dd 3916 {
3917 if (ctype_isRealSU (uentry_getType (ce))
3918 && !uentry_isAnyParam (ce)
3919 && !uentry_isRefParam (ce)
3920 && !uentry_isStatic (ce)
3921 && !sRef_isDependent (sr)
3922 && !sRef_isOwned (sr))
3923 {
3924 sRefSet als = usymtab_allAliases (sr);
616915dd 3925
3926 if (sRefSet_isEmpty (als))
3927 {
2e127cb8 3928 transferChecks_localDestroyed (sr, g_currentloc);
616915dd 3929 }
3930 else
3931 {
3932 /* aliased, no problem */ ;
3933 }
3934
3935 sRefSet_free (als);
3936 }
3937 else if
3938 (!uentry_isStatic (ce)
3939 && ((sRef_isNewRef (sr))
3940 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3941 || sRef_isKeep (sr) || sRef_isOwned (sr))
3942 && !sRef_isDead (sr))
3943 && (!sRef_definitelyNull (sr))
28bf4b0b 3944 && (!usymtab_isDefinitelyNull (sr)))))
616915dd 3945 {
3946 bool hasError = TRUE;
3947
28bf4b0b 3948 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3949
616915dd 3950 /*
3951 ** If its a scope exit, check if there is an alias.
3952 ** If so, make it only. If not, there is an error.
3953 */
3954
3955 if (!isReturn)
3956 {
2e127cb8 3957 if (transferChecks_canLoseReference (sr, g_currentloc))
616915dd 3958 {
28bf4b0b 3959 DPRINTF (("Can lose!"));
616915dd 3960 hasError = FALSE;
3961 }
3962 }
3963
3964 if (hasError)
3965 {
3966 if (sRef_hasLastReference (sr))
3967 {
3968 sRef ar = sRef_getAliasInfoRef (sr);
3969
3970 if (optgenerror
2e127cb8 3971 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
616915dd 3972 message
3973 ("Last reference %q to %s storage %qnot %q before %q",
3974 sRef_unparse (sr),
3975 alkind_unparse (sRef_getAliasKind (sr)),
3976 sRef_unparseOpt (ar),
3977 cstring_makeLiteral (sRef_isKeep (sr)
3978 ? "transferred" : "released"),
3979 cstring_makeLiteral (isReturn
3980 ? "return" : "scope exit")),
3981 g_currentloc))
3982 {
3983 sRef_showRefLost (sr);
3984 }
3985 }
3986 else if (sRef_isNewRef (sr))
3987 {
3988 if (optgenerror
2e127cb8 3989 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
616915dd 3990 message
3991 ("%q %q not released before %q",
3992 cstring_makeLiteral
3993 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
3994 ? "Kill reference parameter" : "New reference"),
3995 uentry_getName (ce),
3996 cstring_makeLiteral (isReturn
3997 ? "return" : "scope exit")),
3998 g_currentloc))
3999 {
4000 sRef_showAliasInfo (sr);
4001 }
4002 }
4003 else
4004 {
4005 if (ctype_isRealSU (sRef_getType (sr)))
4006 {
2e127cb8 4007 transferChecks_structDestroyed (sr, g_currentloc);
616915dd 4008 }
4009 else
4010 {
28bf4b0b 4011 DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
4012
616915dd 4013 if (optgenerror
2e127cb8 4014 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
616915dd 4015 message
4016 ("%s storage %q not %q before %q",
4017 alkind_capName (sRef_getAliasKind (sr)),
4018 uentry_getName (ce),
4019 cstring_makeLiteral (sRef_isKeep (sr)
4020 ? "transferred" : "released"),
4021 cstring_makeLiteral (isReturn
4022 ? "return" : "scope exit")),
4023 g_currentloc))
4024 {
4025 sRef_showAliasInfo (sr);
28bf4b0b 4026 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
616915dd 4027 }
4028 }
4029 }
4030 }
4031 }
4032 else
4033 {
4034 ;
4035 }
4036 }
3e3ec469 4037 }
4038
a956d444 4039 if (mustDefine && uentry_isOut (ce))
3e3ec469 4040 {
a956d444 4041 /* No error if its dead (either only or error already reported */
4042 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
616915dd 4043 {
3e3ec469 4044 voptgenerror
4045 (FLG_MUSTDEFINE,
4046 message ("Out storage %q not defined before %q",
4047 uentry_getName (ce),
4048 cstring_makeLiteral
4049 (isReturn ? "return" : "scope exit")),
4050 g_currentloc);
2e127cb8 4051
4052 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
616915dd 4053 }
3e3ec469 4054 }
4055
4056 /*
4057 ** also check state is okay
4058 */
4059
4060 if (usymtab_lexicalLevel () > functionScope
4061 && uentry_isVariable (ce)
4062 && (sRef_isLocalVar (sr)
4063 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4064 {
4065 sRefSet ab = usymtab_aliasedBy (sr);
616915dd 4066
3e3ec469 4067 /* should do something more efficient here */
28bf4b0b 4068
3e3ec469 4069 if (sRefSet_isEmpty (ab))
616915dd 4070 {
3e3ec469 4071 /* and no local ref */
4072 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
2e127cb8 4073 transferChecks_loseReference (ce);
616915dd 4074 }
3e3ec469 4075 else
616915dd 4076 {
4077 ;
4078 }
4079
3e3ec469 4080 sRefSet_free (ab);
616915dd 4081 }
3e3ec469 4082 else
4083 {
4084 ;
4085 }
4086
4087 checked = sRefSet_insert (checked, sr);
616915dd 4088 }
28bf4b0b 4089
616915dd 4090 llassert (usymtab_isDefined (stab->env));
4091
4092 if (usymtab_isBranch (stab))
4093 {
4094 stab = usymtab_dropEnv (stab);
4095 }
4096 else
4097 {
4098 stab = stab->env;
4099 }
28bf4b0b 4100
616915dd 4101 llassert (stab != usymtab_undefined);
4102 } while (isReturn && (stab->lexlevel >= paramsScope));
28bf4b0b 4103
4104 sRefSet_free (checked);
4105
616915dd 4106 /*
4107 ** for returns:
4108 ** all globals are appropriately defined
4109 ** all parameters are appropriately defined
4110 ** special clauses are followed
4111 */
4112
4113 if (isReturn || (utab->lexlevel == paramsScope))
4114 {
4115 uentry fcn = context_getHeader ();
4116 uentryList params = context_getParams ();
4117 globSet uglobs = context_getUsedGlobs ();
4118 globSet sglobs = context_getGlobs ();
616915dd 4119
4120 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4121 {
4122 aliasTable_checkGlobs (utab->aliases);
4123 }
4124
4125 /*
28bf4b0b 4126 ** state clauses (ensures, defines, sets, allocates, releases)
616915dd 4127 */
28bf4b0b 4128
4129 if (uentry_hasStateClauseList (fcn))
616915dd 4130 {
28bf4b0b 4131 stateClauseList clauses = uentry_getStateClauseList (fcn);
616915dd 4132
28bf4b0b 4133 stateClauseList_elements (clauses, cl)
616915dd 4134 {
28bf4b0b 4135 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4136 {
4137 if (stateClause_setsMetaState (cl))
616915dd 4138 {
28bf4b0b 4139 sRefSet rfs = stateClause_getRefs (cl);
4140 qual q = stateClause_getMetaQual (cl);
4141 annotationInfo ainfo = qual_getAnnotationInfo (q);
4142 metaStateInfo minfo = annotationInfo_getState (ainfo);
4143 cstring key = metaStateInfo_getName (minfo);
4144 int mvalue = annotationInfo_getValue (ainfo);
4145
4146 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4147
4148 sRefSet_elements (rfs, el)
616915dd 4149 {
28bf4b0b 4150 sRef base = sRef_getRootBase (el);
616915dd 4151
28bf4b0b 4152 if (sRef_isResult (base))
4153 {
4154 /*
4155 ** This is checked for return transfers.
4156 */
4157 ;
4158 }
4159 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
616915dd 4160 {
28bf4b0b 4161 sRef sr = sRef_updateSref (base);
4162 sr = sRef_fixBase (el, sr);
4163
4164 if (!sRef_checkMetaStateValue (sr, key, mvalue))
616915dd 4165 {
28bf4b0b 4166 if (optgenerror
4167 (FLG_STATETRANSFER,
4168 message
2c88d156 4169 ("Ensures clause not satisfied%q (state is %q): %q",
28bf4b0b 4170 sRef_isGlobalMarker (sr)
4171 ? message ("")
4172 : message (" by %q", sRef_unparse (sr)),
4173 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4174 minfo),
4175 stateClause_unparse (cl)),
4176 g_currentloc))
616915dd 4177 {
28bf4b0b 4178 sRef_showMetaStateInfo (sr, key);
4179 }
4180 }
616915dd 4181 }
28bf4b0b 4182 else
4183 {
4184 if (sRef_isMeaningful (el))
4185 {
4186 BADBRANCH;
4187 }
4188 }
4189 } end_sRefSet_elements ;
4190 }
4191 else
4192 {
4193 /* evs - 2000 07 10 - added this */
4194 sRefTest tst = stateClause_getPostTestFunction (cl);
4195 sRefSet rfs = stateClause_getRefs (cl);
4196
4197 sRefSet_elements (rfs, el)
616915dd 4198 {
28bf4b0b 4199 sRef base = sRef_getRootBase (el);
4200
4201 if (sRef_isResult (base))
616915dd 4202 {
28bf4b0b 4203 /*
4204 ** This is checked for return transfers.
4205 */
4206
4207 ;
616915dd 4208 }
28bf4b0b 4209 else if (sRef_isParam (base))
4210 {
4211 sRef sr = sRef_updateSref (base);
4212 sr = sRef_fixBase (el, sr);
4213
4214 if (tst != NULL && !tst (sr))
4215 {
4216 if (optgenerror
4217 (stateClause_postErrorCode (cl),
4218 message ("%s storage %qcorresponds to "
4219 "storage listed in %q clause",
4220 stateClause_postErrorString (cl, sr),
4221 sRef_unparseOpt (sr),
4222 stateClause_unparseKind (cl)),
4223 g_currentloc))
4224 {
4225 sRefShower ss = stateClause_getPostTestShower (cl);
4226
4227 if (ss != NULL)
4228 {
4229 ss (sr);
4230 }
1d239d69 4231
3120b462 4232 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
28bf4b0b 4233 }
4234 }
4235 }
4236 else
4237 {
4238 if (sRef_isMeaningful (el))
4239 {
4240 BADBRANCH;
4241 }
4242 }
4243 } end_sRefSet_elements ;
4244 }
616915dd 4245 }
28bf4b0b 4246 } end_stateClauseList_elements ;
616915dd 4247 }
4248
4249 /*
4250 ** check parameters on return
4251 */
4252
4253 uentryList_elements (params, arg)
4254 {
4255 if (!uentry_isElipsisMarker (arg))
4256 {
4257 ctype rt = ctype_realType (uentry_getType (arg));
4258
4259 if (ctype_isMutable (rt) || ctype_isSU (rt))
4260 {
4261 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
28bf4b0b 4262 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
2e127cb8 4263 transferChecks_paramReturn (param);
616915dd 4264 }
4265 }
4266 } end_uentryList_elements;
4267
28bf4b0b 4268 DPRINTF (("Check global return: %s",
4269 globSet_unparse (sglobs)));
4270
616915dd 4271 globSet_allElements (sglobs, el)
4272 {
28bf4b0b 4273 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
616915dd 4274 uentry current = sRef_getUentry (el);
4275
28bf4b0b 4276 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4277 uentry_unparseFull (current)));
4278
616915dd 4279 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4280 {
28bf4b0b 4281 checkGlobalReturn (current, orig);
616915dd 4282 }
4283 } end_globSet_allElements;
4284
4285 globSet_allElements (uglobs, el)
4286 {
4287 if (!globSet_member (sglobs, el))
4288 {
4289 uentry current = sRef_getUentry (el);
4290
616915dd 4291 if (uentry_isVariable (current)
4292 && !uentry_isRealFunction (current))
4293 {
4294 checkGlobalReturn (current, sRef_undefined);
4295 }
4296 }
4297 } end_globSet_allElements;
28bf4b0b 4298 }
4299}
616915dd 4300
4301void
4302usymtab_quietExitScope (fileloc loc)
4303 /*@globals utab, globtab, filetab; @*/
4304 /*@modifies utab@*/
4305{
4306 usymtab t = utab->env;
4307
4308 if (utab->reftable != NULL)
4309 {
4310 int i;
4311
4312 for (i = 0; i < utab->nentries; i++)
4313 {
4314 uentry current = utab->entries[i];
4315 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4316
4317 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4318 }
4319 }
4320
4321 llassert (t != NULL);
4322
4323 if (t->lexlevel > paramsScope)
4324 {
4325 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4326 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4327 t->lexlevel);
4328 utab->aliases = aliasTable_undefined;
4329 }
4330
4331 t->mustBreak = utab->mustBreak;
4332 t->exitCode = utab->exitCode;
4333
4334 usymtab_freeLevel (utab);
4335
4336 utab = t;
4337}
4338
4339/*
4340** Exit a scope with no checking, lose alias states.
4341** (When should this be used?)
4342*/
4343
4344void usymtab_quietPlainExitScope (void)
4345 /*@globals utab, globtab, filetab@*/
4346 /*@modifies utab@*/
4347{
4348 usymtab t = utab->env;
4349
4350 llassert (t != NULL);
4351 llassert (NOALIAS (utab->aliases, t->aliases));
4352 usymtab_freeLevel (utab);
4353 utab = t;
4354}
4355
4356void usymtab_exitScope (exprNode expr)
4357 /*@globals utab, filetab, globtab@*/
4358 /*@modifies utab, globtab@*/
4359{
4360 usymtab ctab = usymtab_undefined;
4361 usymtab lctab = usymtab_undefined;
4362 bool mustReturn = exprNode_mustEscape (expr);
28bf4b0b 4363
4364 DPRINTF (("Exit scope"));
4365
616915dd 4366 if (utab->kind == US_CBRANCH)
4367 {
4368 /*
4369 ** save the case branches, remove the first non-cbranch
4370 */
4371
4372 ctab = utab;
4373
4374 while (utab->kind == US_CBRANCH)
4375 {
4376 lctab = utab;
4377 utab = utab->env;
4378 llassert (utab != GLOBAL_ENV);
4379 }
4380 }
4381
4382 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4383 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH) {
4384
4385 if (context_inMacro ()) {
4386 /* evs 2000-07-25 */
4387 /* Unparseable macro may end inside nested scope. Deal with it. */
4388
28bf4b0b 4389 llerror (FLG_SYNTAX,
4390 message ("Problem parsing macro body of %s (unbalanced scopes). "
4391 "Attempting to recover, recommend /*@notfunction@*/ before "
4392 "macro definition.",
4393 context_inFunctionName ()));
616915dd 4394
4395 while (utab->kind == US_TBRANCH
4396 || utab->kind == US_FBRANCH
4397 || utab->kind == US_CBRANCH
4398 || utab->kind == US_SWITCH)
4399 {
4400 utab = utab->env;
4401 llassert (utab != GLOBAL_ENV);
4402 }
4403 } else {
28bf4b0b 4404 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
616915dd 4405 /*@-branchstate@*/
4406 } /*@=branchstate@*/
4407 }
4408
4409 /*
4410 ** check all variables in scope were used
4411 */
4412
4413 /*
4414 ** bogus errors if this is the normal inside a switch,
4415 ** since cases have not been merged yet. Should probably
4416 ** still check this, but I'm too lazy at the moment...
4417 */
4418
4419 llassertfatal (utab->env != GLOBAL_ENV);
4420
4421 if (utab->env->kind != US_SWITCH)
4422 {
4423 usymtab_allUsed ();
4424 }
4425
4426 /*
4427 ** check aliasing: all only params are released (dead)
4428 ** definition: all out params are defined, all modified params
4429 ** are completely defined
4430 **
4431 ** NOTE: note for exiting paramsScope, since checkReturn should be
4432 ** called first.
4433 */
4434
4435 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4436 {
4437 /*
4438 ** should only call this is end of scope is reachable...
4439 */
4440
4441 usymtab_checkFinalScope (FALSE);
4442 }
4443
4444 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4445 {
4446 /*
4447 ** leaving a function, need to fix up globals
4448 */
4449
4450 uentryList params = context_getParams ();
4451 globSet globs = context_getUsedGlobs ();
4452
4453
4454 uentryList_elements (params, ue)
4455 {
4456 uentry_fixupSref (ue);
4457 } end_uentryList_elements;
4458
4459 clearFunctionTypes ();
4460
4461
4462 globSet_allElements (globs, el)
4463 {
4464 if (sRef_isCvar (el))
4465 {
4466 uentry current;
4467 int index = sRef_getScopeIndex (el);
4468
4469 if (sRef_isFileStatic (el))
4470 {
4471 llassert (usymtab_isDefined (filetab));
4472 current = usymtab_fetchIndex (filetab, index);
4473 }
4474 else
4475 {
4476 current = usymtab_fetchIndex (globtab, index);
4477 }
4478
4479 if (uentry_isVariable (current))
4480 {
4481 uentry_fixupSref (current);
4482 }
4483 else
4484 {
4485 sRef_clearDerived (uentry_getSref (current));
4486 }
4487 }
4488 } end_globSet_allElements;
4489 }
4490
4491 usymtab_quietExitScope (exprNode_loc (expr));
4492
4493 if (lctab != usymtab_undefined)
4494 {
4495 /*@i@*/ lctab->env = utab;
4496 /*@i@*/ utab = ctab;
4497 /*@-branchstate@*/ } /*@=branchstate@*/
146e25eb 4498 /*@-globstate@*/
4499/*@i523@*/ }
616915dd 4500/*@=globstate@*/
4501
4502/*
4503** yikes! don't let the '170 kids see this one...
4504*/
4505
4506int
4507uentry_directParamNo (uentry ue)
4508{
4509 if (uentry_isVar (ue))
4510 {
4511 sRef sr = uentry_getSref (ue);
4512
4513 if (sRef_lexLevel (sr) == functionScope)
4514 {
abd7f895 4515 int index = sRef_getScopeIndex (sr);
616915dd 4516
4517 if (index < uentryList_size (context_getParams ()))
4518 {
4519 return index;
4520 }
4521 }
4522 }
4523 return -1;
4524}
4525
4526/*@dependent@*/ /*@exposed@*/ uentry
4527 usymtab_getParam (int paramno)
4528 /*@globals utab@*/
4529{
4530 /*
4531 ** requires in a function context (checked)
4532 **
4533 ** depends on no nested functions --- the function
4534 ** parameters are ALWAYS one scope inside the global scope
4535 ** and entered in order!
4536 */
4537 usymtab s = utab;
4538
4539 if (!context_inFunctionLike ())
4540 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4541 context_unparse ()));
4542
4543 while (s->lexlevel > paramsScope)
4544 {
4545 s = s->env;
4546 }
4547
4548 llassert (usymtab_isDefined (s));
4549
4550 if (paramno >= s->nentries)
4551 {
4552 /*
4553 ** Parse errors lead to this.
4554 */
4555
4556 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4557 ctype_unknown);
4558
4559 uentry_markOwned (err);
4560 return (err);
4561 }
4562
4563 return (s->entries[paramno]);
4564}
4565
4566static /*@dependent@*/ /*@exposed@*/ uentry
4567usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4568{
4569 uentry ue;
4570
616915dd 4571 ue = usymtab_getRefNoisy (u, level, index);
4572
616915dd 4573 if (uentry_isUndefined (ue))
4574 {
4575 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4576 index, level));
4577 }
616915dd 4578
4579 return ue;
4580}
4581
4582static /*@dependent@*/ /*@exposed@*/ usymtab
4583 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4584{
4585 if (s->kind == US_CBRANCH)
4586 {
4587 usymtab t = s;
4588
4589 do
4590 {
4591 t = s;
4592 s = s->env;
4593 llassert (s != GLOBAL_ENV);
4594 } while (s->kind == US_CBRANCH);
4595 /* drop all cases (except in nested scopes */
4596
4597 s = t;
4598 llassert (s != GLOBAL_ENV);
4599 }
4600
4601 if (s->kind == US_FBRANCH)
4602 {
4603 s = s->env; /* skip the true branch */
4604 llassert (usymtab_isDefined (s));
4605 llassert (s->kind == US_TBRANCH);
4606 }
4607
4608 llassert (s != GLOBAL_ENV);
4609 s = s->env;
4610
4611 return s;
4612}
4613
4614/*@dependent@*/ /*@exposed@*/ uentry
4615 usymtab_getRefQuiet (int level, usymId index)
4616 /*@globals utab@*/
4617{
4618 usymtab s = utab;
4619
4620
4621 llassert (s != NULL);
4622 llassert (index >= 0);
4623
4624 if (level > s->lexlevel)
28bf4b0b 4625 {
616915dd 4626 return uentry_undefined;
4627 }
4628
4629 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4630 level, s->lexlevel));
4631
4632 while (s->lexlevel > level)
4633 {
4634 if (usymtab_isBranch (s))
4635 {
4636 int eindex = refTable_lookup (s, level, index);
4637
4638 if (eindex != NOT_FOUND)
4639 {
4640 return (s->entries[eindex]);
4641 }
4642 }
4643
4644 s = usymtab_dropEnv (s);
4645 }
4646
4647 while (usymtab_isBranch (s) && s->lexlevel == level)
4648 {
4649 int eindex = refTable_lookup (s, level, index);
4650
4651 if (eindex != NOT_FOUND)
4652 {
4653 return (s->entries[eindex]);
4654 }
4655
4656 s = usymtab_dropEnv (s);
4657 }
4658
4659 if (index >= s->nentries)
4660 {
4661 return uentry_undefined;
4662 }
4663
4664 llassert (!uentry_isUndefined (s->entries[index]));
4665
4666 return s->entries[index];
4667}
4668
4669static /*@dependent@*/ /*@exposed@*/ uentry
4670usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4671{
4672 usymtab otab = s;
4673 uentry ue = uentry_undefined;
616915dd 4674
4675 llassert (index >= 0);
616915dd 4676
4677 while (s->lexlevel > level)
4678 {
616915dd 4679 if (usymtab_isBranch (s))
4680 {
4681 int eindex = refTable_lookup (s, level, index);
4682
4683 if (eindex != NOT_FOUND)
4684 {
4685 ue = s->entries[eindex];
4686
4687 if (s != otab)
4688 {
4689 while (!usymtab_isBranch (otab))
4690 {
4691 otab = usymtab_dropEnv (otab);
4692 llassert (otab != GLOBAL_ENV);
4693 }
4694
4695 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4696 {
4697 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4698 }
4699 else
4700 {
4701 ;
4702 }
4703 }
4704
4705 return ue;
4706 }
4707 }
4708
4709 s = usymtab_dropEnv (s);
4710 }
4711
4712 llassert (usymtab_isDefined (s));
4713
4714 while (usymtab_isBranch (s) && s->lexlevel == level)
4715 {
4716 int eindex = refTable_lookup (s, level, index);
4717
4718
4719 if (eindex != NOT_FOUND)
4720 {
4721 ue = s->entries[eindex];
4722
4723 if (s != otab)
4724 {
4725 while (!usymtab_isBranch (otab))
4726 {
4727 otab = usymtab_dropEnv (otab);
4728 llassert (otab != GLOBAL_ENV);
4729 }
4730
4731 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4732 }
4733 else
4734 {
4735 ;
4736 }
4737
4738 return ue;
4739 }
4740
4741 s = usymtab_dropEnv (s);
4742 }
4743
4744 if (s->lexlevel == level && (index < s->nentries))
4745 {
4746 ue = s->entries[index];
4747
4748 if (uentry_isValid (ue))
4749 {
4750 if (s != otab)
4751 {
4752 while (!usymtab_isBranch (otab))
4753 {
4754 otab = usymtab_dropEnv (otab);
4755
4756 if (otab == GLOBAL_ENV)
4757 {
4758 return ue;
4759 }
4760 }
4761
4762 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4763 }
4764 else
4765 {
28bf4b0b 4766 }
616915dd 4767 }
28bf4b0b 4768
616915dd 4769 return ue;
4770 }
4771
4772
4773 if (index >= s->nentries)
4774 {
4775 return uentry_undefined;
4776 }
4777
4778 llassert (!uentry_isUndefined (s->entries[index]));
4779
4780 return s->entries[index];
4781}
4782
4783/*
4784** looking up entries
4785**
4786** If entry is inside a branch, then copy it, and put it into
4787** the branch table.
4788*/
4789
4790static
4791int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4792{
4793 refTable rt = ut->reftable;
4794 int i;
4795
4796 llassert (rt != NULL);
4797
616915dd 4798 for (i = 0; i < ut->nentries; i++)
4799 {
4800 if (rt[i]->level == level && rt[i]->index == index)
4801 {
28bf4b0b 4802 return i;
616915dd 4803 }
4804 }
28bf4b0b 4805
4806 return NOT_FOUND;
616915dd 4807}
4808
4809static
4810/*@only@*/ refentry refentry_create (int level, int index)
4811{
4812 refentry r = (refentry) dmalloc (sizeof (*r));
4813
4814 r->level = level;
4815 r->index = index;
4816
4817 return r;
4818}
4819
4820static /*@dependent@*/ /*@exposed@*/ uentry
4821usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4822{
4823 int eindex;
4824 usymtab ut = s;
4825
28bf4b0b 4826 if (ut->reftable == NULL)
4827 {
4828 DPRINTF (("Adding ref entry without reftable: %s", k));
4829 return uentry_undefined;
4830 }
616915dd 4831
28bf4b0b 4832 llassert (ut->reftable != NULL);
4833
616915dd 4834 while (s != GLOBAL_ENV)
4835 {
4836 eindex = usymtab_getIndex (s, k);
4837
4838 if (eindex != NOT_FOUND)
4839 {
4840 uentry current = s->entries[eindex];
4841
4842 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4843 {
4844 uentry ue;
4845
28bf4b0b 4846 DPRINTF (("Here: copying %s", uentry_unparse (current)));
616915dd 4847 ue = uentry_copy (current);
28bf4b0b 4848 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
616915dd 4849 usymtab_addEntryQuiet (ut, ue);
28bf4b0b 4850 DPRINTF (("Okay..."));
4851
616915dd 4852 if (s->reftable != NULL)
4853 {
4854 refentry ref = s->reftable[eindex];
616915dd 4855
4856 ut->reftable[ut->nentries - 1]
4857 = refentry_create (ref->level, ref->index);
4858 }
4859 else
4860 {
4861 ut->reftable[ut->nentries - 1]
4862 = refentry_create (s->lexlevel, eindex);
4863 }
4864
4865 return (ue);
4866 }
4867 else
4868 {
4869 return (current);
4870 }
4871 }
4872
4873 s = usymtab_dropEnv (s);
4874 }
4875
4876 return uentry_undefined;
4877}
4878
4879static uentry usymtab_lookupAux (usymtab s, cstring k)
4880{
4881 DPRINTF (("Lookup: %s", k));
4882
4883 while (s != GLOBAL_ENV)
4884 {
4885 int eindex = usymtab_getIndex (s, k);
4886
4887 if (eindex != NOT_FOUND)
4888 {
4889 uentry ret = s->entries[eindex];
28bf4b0b 4890# if 0
4891
616915dd 4892
28bf4b0b 4893 if (s->kind == US_TBRANCH
4894 || s->kind == US_FBRANCH
4895 || s->kind == US_CBRANCH)
4896 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4897 {
4898 uentry ret;
4899 DPRINTF (("Adding global ref entry: %s", k));
4900 ret = usymtab_addRefEntry (os, k);
4901 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4902 return ret;
4903 }
4904
4905# endif
616915dd 4906 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4907 return (ret);
4908 }
28bf4b0b 4909
616915dd 4910 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4911 || s->kind == US_CBRANCH)
4912 {
28bf4b0b 4913 /* why isn't this os??? */
616915dd 4914 uentry ret = usymtab_addRefEntry (s, k);
28bf4b0b 4915 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
616915dd 4916 return ret;
4917 }
4918
4919 s = s->env;
4920 }
4921
4922 return uentry_undefined;
4923}
4924
4925static /*@dependent@*/ /*@exposed@*/ uentry
28bf4b0b 4926usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
616915dd 4927{
4928 int eindex;
4929
4930 while (s != GLOBAL_ENV)
4931 {
4932 eindex = usymtab_getIndex (s, k);
4933
4934 if (eindex != NOT_FOUND)
4935 {
4936 uentry ret = s->entries[eindex];
4937 return (ret);
4938 }
4939
28bf4b0b 4940 if (noalt && usymtab_isBranch (s))
4941 {
4942 s = usymtab_dropEnv (s);
4943 }
4944 else
4945 {
abd7f895 4946 llassert (s != NULL); /*@i523 should not need this? */
28bf4b0b 4947 s = s->env;
4948 }
616915dd 4949 }
4950
4951 return uentry_undefined;
4952}
4953
28bf4b0b 4954static /*@exposed@*/ /*@dependent@*/ uentry
4955usymtab_lookupQuiet (usymtab s, cstring k)
4956{
4957 return usymtab_lookupQuietAux (s, k, FALSE);
4958}
4959
4960static /*@exposed@*/ /*@dependent@*/ uentry
4961usymtab_lookupQuietNoAlt (usymtab s, cstring k)
4962{
4963 return usymtab_lookupQuietAux (s, k, TRUE);
4964}
4965
616915dd 4966/*@dependent@*/ /*@observer@*/ uentry
4967 usymtab_lookupSafe (cstring k)
4968 /*@globals utab@*/
4969{
4970 DPRINTF (("Lookup safe: %s", k));
4971 return (usymtab_lookupAux (utab, k));
4972}
4973
4974uentry
4975 usymtab_lookupExpose (cstring k)
4976 /*@globals utab@*/
4977{
4978 uentry ce = usymtab_lookupAux (utab, k);
4979
4980 if (uentry_isUndefined (ce))
4981 {
4982 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
4983 }
4984
4985 if (uentry_isPriv (ce))
4986 {
4987 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
4988 }
4989
4990 return ce;
4991}
4992
4993uentry usymtab_lookupExposeGlob (cstring k)
4994{
4995 return (usymtab_lookupGlobSafe (k));
4996}
4997
4998uentry usymtab_lookupGlob (cstring k)
4999 /*@globals globtab@*/
5000{
5001 uentry ce = usymtab_lookupAux (globtab, k);
5002
5003 if (uentry_isUndefined (ce))
5004 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5005
5006 if (uentry_isPriv (ce))
5007 llfatalbug (message ("usymtab_lookup: private: %s", k));
5008
5009 return ce;
5010}
5011
5012/*@observer@*/ uentry
5013 usymtab_lookupGlobSafe (cstring k)
5014 /*@globals globtab@*/
5015{
5016 uentry ce = usymtab_lookupAux (globtab, k);
5017
5018 return ce;
5019}
5020
5021uentry usymtab_lookupEither (cstring k)
5022 /*@globals utab@*/
5023{
5024 uentry ce = usymtab_lookupSafe (k);
5025
5026 if (uentry_isUndefined (ce))
5027 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5028
5029 return ce;
5030}
5031
5032# ifndef NOLCL
5033ctype
5034usymtab_lookupType (cstring k)
5035 /*@globals globtab@*/
5036{
5037 usymId uid = usymtab_getTypeId (k);
5038
5039 if (uid == USYMIDINVALID)
5040 {
5041 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5042 return ctype_unknown;
5043 }
5044
5045 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5046}
5047# endif
5048
5049ctype
5050usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5051{
5052 usymId uid = usymtab_getTypeId (k);
5053
5054 if (uid == USYMIDINVALID)
5055 {
5056 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5057 return ctype_unknown;
5058 }
5059
5060 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5061}
5062
5063/*
5064** if there is an unnamed lcl-specified struct tag matching
5065** the uentryList, return its datatype. Otherwise, returns
5066** ctype_undefined.
5067*/
5068
5069ctype
5070usymtab_structFieldsType (uentryList f)
5071 /*@globals globtab@*/
5072{
5073 return (usymtab_suFieldsType (f, TRUE));
5074}
5075
5076ctype
5077usymtab_unionFieldsType (uentryList f)
5078 /*@globals globtab@*/
5079{
5080 return (usymtab_suFieldsType (f, FALSE));
5081}
5082
5083static ctype
5084usymtab_suFieldsType (uentryList f, bool isStruct)
5085 /*@globals globtab@*/
5086{
5087 int i;
5088
28bf4b0b 5089 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5090
5091 if (fileloc_isSpec (g_currentloc))
5092 {
5093 return (ctype_undefined);
5094 }
616915dd 5095
5096 for (i = 0; i < globtab->nentries; i++)
5097 {
5098 uentry current = globtab->entries[i];
5099
5100 if ((isStruct
5101 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5102 {
5103 if (isFakeTag (uentry_rawName (current)))
5104 {
5105 ctype ct = uentry_getType (current);
28bf4b0b 5106
5107 DPRINTF (("Check: %s", ctype_unparse (ct)));
616915dd 5108
5109 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
28bf4b0b 5110 &&
5111 (uentry_isSpecified (current)
5112 && uentryList_equivFields (f, ctype_getFields (ct))))
616915dd 5113 {
28bf4b0b 5114 return uentry_getAbstractType (current);
5115 }
5116 else
5117 {
5118 ;
616915dd 5119 }
5120 }
5121 }
5122 }
5123
5124 return ctype_undefined;
5125}
5126
5127ctype
5128 usymtab_enumEnumNameListType (enumNameList f)
5129 /*@globals globtab@*/
5130{
5131 int i;
5132
5133 for (i = 0; i < globtab->nentries; i++)
5134 {
5135 uentry current = globtab->entries[i];
5136
5137 if (uentry_isEnumTag (current))
5138 {
5139 if (isFakeTag (uentry_rawName (current)))
5140 {
5141 ctype ct = uentry_getType (current);
5142
5143 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5144 {
5145 return uentry_getType (current);
5146 }
5147 }
5148 }
5149 }
5150
5151 return ctype_undefined;
5152}
5153
5154bool
5155usymtab_exists (cstring k)
5156 /*@globals utab@*/
5157{
5158 uentry ce = usymtab_lookupSafe (k);
616915dd 5159 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5160}
5161
5162bool
5163usymtab_existsReal (cstring k)
5164 /*@globals utab@*/
5165{
5166 uentry ce = usymtab_lookupSafe (k);
5167
5168 return (!(uentry_isUndefined (ce))
5169 && !(uentry_isPriv (ce))
5170 && !(uentry_isExpandedMacro (ce)));
5171}
5172
5173bool
5174 usymtab_existsGlob (cstring k)
5175 /*@globals globtab@*/
5176{
5177 uentry ce = usymtab_lookupAux (globtab, k);
5178
5179 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5180}
5181
5182# ifndef NOLCL
5183bool
5184usymtab_existsEither (cstring k)
5185 /*@globals utab@*/
5186{
5187 uentry ce = usymtab_lookupAux (utab, k);
5188
5189 return (uentry_isValid (ce));
5190}
5191
5192bool
5193 usymtab_existsGlobEither (cstring k)
5194 /*@globals globtab@*/
5195{
5196 uentry ce = usymtab_lookupAux (globtab, k);
5197
5198 return (uentry_isValid (ce));
5199}
5200# endif
5201
5202bool
5203usymtab_existsType (cstring k)
5204 /*@globals globtab@*/
5205{
5206 uentry ce = usymtab_lookupAux (globtab, k);
5207
5208 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5209}
5210
5211bool
5212usymtab_existsTypeEither (cstring k)
5213 /*@globals globtab@*/
5214{
28bf4b0b 5215 uentry ce;
5216 ce = usymtab_lookupAux (globtab, k);
5217 return (uentry_isValid (ce) && uentry_isDatatype (ce));
616915dd 5218}
5219
5220bool
5221usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5222{
5223 cstring sname = makeStruct (k);
5224 uentry ce = usymtab_lookupAux (globtab, sname);
28bf4b0b 5225 cstring_free (sname);
616915dd 5226 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5227}
5228
5229bool
5230usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5231{
5232 cstring uname = makeUnion (k);
5233 uentry ce = usymtab_lookupAux (globtab, uname);
5234
5235 cstring_free (uname);
5236
5237 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5238}
5239
5240bool
5241usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5242{
5243 cstring ename = makeEnum (k);
5244 uentry ce = usymtab_lookupAux (globtab, ename);
5245
5246 cstring_free (ename);
5247 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5248}
5249
5250# ifndef NOLCL
5251bool usymtab_existsVar (cstring k)
5252 /*@globals utab@*/
5253{
5254 uentry ce = usymtab_lookupSafe (k);
5255
5256 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5257}
5258# endif
5259
5260/*
5261** destructors
5262*/
5263
5264static void
5265refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5266{
5267 if (x != NULL)
5268 {
5269 int i;
5270
5271 for (i = 0; i < nentries; i++)
5272 {
5273 sfree (x[i]);
5274 }
5275
5276 sfree (x);
5277 }
5278}
5279
5280static void
5281usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5282 /*@globals globtab, utab, filetab@*/
5283{
5284 int i;
5285
5286 aliasTable_free (u->aliases);
28bf4b0b 5287
616915dd 5288 refTable_free (u->reftable, u->nentries);
5289
5290 if (u == filetab || u == globtab)
5291 {
5292 for (i = 0; i < u->nentries; i++)
5293 {
5294 uentry_freeComplete (u->entries[i]);
5295 }
5296 }
5297 else
5298 {
5299 for (i = 0; i < u->nentries; i++)
5300 {
5301 uentry_free (u->entries[i]);
5302 }
5303 }
5304
5305 guardSet_free (u->guards);
5306 sfree (u->entries);
5307
5308 if (u != globtab
5309 && u != utab
5310 && u != filetab)
5311 {
28bf4b0b 5312 llassert (!cstringTable_isDefined (u->htable));
616915dd 5313 sfree (u);
5314 }
5315
5316/*@-mustfree@*/
5317} /*@=mustfree@*/
5318
5319static void
5320usymtab_freeAux (/*@only@*/ usymtab u)
5321 /*@globals globtab, utab, filetab@*/
5322 /*@modifies u@*/
5323{
5324 while (u != GLOBAL_ENV)
5325 {
5326 usymtab t = u->env;
5327 usymtab_freeLevel (u);
5328 u = t;
5329 /*@-branchstate@*/
5330 }
5331 /*@=branchstate@*/
5332}
5333
5334void usymtab_free ()
5335 /*@globals killed utab, globtab, filetab@*/
5336 /*@modifies utab@*/
5337{
5338 dbgfree = TRUE;
5339 usymtab_freeAux (utab);
5340}
5341
5342static int usymtab_lexicalLevel (void) /*@globals utab@*/
5343{
5344 return (utab->lexlevel);
5345}
5346
5347bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5348{
5349 return (utab == globtab);
5350}
5351
5352bool usymtab_inFileScope () /*@globals utab@*/
5353{
5354 return (utab->lexlevel == fileScope);
5355}
5356
5357bool usymtab_inFunctionScope () /*@globals utab@*/
5358{
5359 return (utab->lexlevel == functionScope);
5360}
5361
5362# ifndef NOLCL
5363void
5364usymtab_replaceEntry (uentry s)
5365 /*@globals utab, globtab@*/
5366 /*@modifies utab, s@*/
5367{
5368 usymtab_replaceEntryAux (utab, s);
5369}
5370# endif
5371
5372bool
5373usymtab_matchForwardStruct (usymId u1, usymId u2)
5374 /*@globals globtab@*/
5375{
5376 uentry ue1 = usymtab_getTypeEntry (u1);
5377 uentry ue2 = usymtab_getTypeEntry (u2);
5378
5379 if (uentry_isAnyTag (ue2))
5380 {
5381 ctype reptype = uentry_getType (ue1);
5382
5383 if (ctype_isPointer (reptype))
5384 {
5385 ctype repbase = ctype_getBaseType (reptype);
5386
5387 if (ctype_isUA (repbase))
5388 {
5389 typeId rtuid = ctype_typeId (repbase);
5390
5391 if (u2 == rtuid) return TRUE;
5392
5393 if (usymId_isValid (rtuid))
5394 {
5395 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5396
5397 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5398 }
5399 }
5400 }
5401 }
5402
5403 return FALSE;
5404}
5405
5406void usymtab_addGuards (guardSet guards)
5407 /*@modifies utab@*/
5408{
5409 utab->guards = guardSet_union (utab->guards, guards);
5410 }
5411
5412static bool usymtab_isGuardedAux (sRef s)
5413 /*@globals utab@*/
5414{
5415 usymtab tab = utab;
5416 sRef base = sRef_getRootBase (s);
5417 int lowlevel = paramsScope;
5418 int baselevel = sRef_lexLevel (base);
5419
5420 if (sRef_isCvar (base))
5421 {
5422 lowlevel = baselevel;
5423 if (lowlevel < paramsScope) lowlevel = paramsScope;
5424 }
5425
5426 while (tab->lexlevel >= lowlevel)
5427 {
2209bcb7 5428 DPRINTF (("Is guarded? [%s] %s",
5429 guardSet_unparse (tab->guards),
5430 sRef_unparseFull (s)));
5431
616915dd 5432 if (guardSet_isGuarded (tab->guards, s))
5433 {
5434 /*
5435 if (!sRef_definitelyNull (s))
5436 {
5437 sRef_setNotNull (s, fileloc_undefined);
5438 }
5439 */
5440 return TRUE;
5441 }
5442
5443 tab = usymtab_dropEnv (tab);
5444 }
5445
5446 return FALSE;
5447}
5448
5449void usymtab_unguard (sRef s) /*@modifies utab@*/
5450{
5451 usymtab tab = utab;
5452 sRef base = sRef_getRootBase (s);
5453 int lowlevel = paramsScope;
5454 int baselevel = sRef_lexLevel (base);
5455
5456 if (sRef_isCvar (base))
5457 {
5458 lowlevel = baselevel;
5459 if (lowlevel < paramsScope) lowlevel = paramsScope;
5460 }
5461
5462 while (tab->lexlevel >= lowlevel)
5463 {
5464 if (guardSet_isGuarded (tab->guards, s))
5465 {
5466 guardSet_delete (tab->guards, s);
5467 }
5468
5469 tab = usymtab_dropEnv (tab);
5470 }
5471}
5472
5473bool usymtab_isGuarded (sRef s)
5474{
2209bcb7 5475 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
616915dd 5476 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5477}
5478
28bf4b0b 5479bool usymtab_isDefinitelyNull (sRef s)
616915dd 5480{
28bf4b0b 5481 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
616915dd 5482}
5483
28bf4b0b 5484bool usymtab_isDefinitelyNullDeep (sRef s)
616915dd 5485{
28bf4b0b 5486 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
616915dd 5487}
5488
28bf4b0b 5489static bool usymtab_isDefinitelyNullAux (sRef s)
616915dd 5490 /*@globals utab@*/
5491{
5492 usymtab tab = utab;
5493 sRef base = sRef_getRootBase (s);
5494 int lowlevel = paramsScope;
5495
5496 if (sRef_isCvar (base))
5497 {
5498 lowlevel = sRef_lexLevel (base);
5499 if (lowlevel < paramsScope) lowlevel = paramsScope;
5500 }
5501
5502 while (tab->lexlevel >= lowlevel)
5503 {
28bf4b0b 5504 if (guardSet_mustBeNull (tab->guards, s))
616915dd 5505 {
5506 return TRUE;
5507 }
5508
5509 while (tab->kind == US_CBRANCH)
5510 {
5511 tab = tab->env;
5512 }
5513
5514 llassert (usymtab_isDefined (tab));
5515
5516 if (tab->kind == US_FBRANCH)
5517 {
5518 tab = tab->env;
5519 llassert (tab->kind == US_TBRANCH);
5520 }
5521
5522 tab = tab->env;
5523 }
5524
5525 return FALSE;
5526}
5527
5528void
5529usymtab_printGuards ()
5530 /*@globals utab, globtab@*/
5531{
5532 usymtab ttab = utab;
5533
5534 while (ttab != globtab)
5535 {
5536 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5537 guardSet_unparse (ttab->guards)));
5538 ttab = ttab->env;
5539 }
5540}
5541
5542void
5543usymtab_displayAllUses ()
5544 /*@globals utab, globtab@*/
5545{
5546 usymtab copy;
5547
5548 /* only in top scope */
5549 llassert (utab == globtab);
5550
5551 /* need a copy, so order is not messed up by sort! */
5552 copy = usymtab_shallowCopy (globtab);
5553
5554 qsort (copy->entries, (size_t)copy->nentries,
5555 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5556
5557 usymtab_entries (copy, ue)
5558 {
5559 if (uentry_isValid (ue))
5560 {
5561 filelocList uses = uentry_getUses (ue);
5562 int size = filelocList_realSize (uses);
5563
5564 if (fileloc_isDefined (uentry_whereDefined (ue))
5565 && !fileloc_isLib (uentry_whereDefined (ue))
5566 && (size > 0))
5567 {
28bf4b0b 5568 llmsg (message ("%q (%q), %d use%&:\n %q",
616915dd 5569 uentry_getName (ue),
5570 fileloc_unparse (uentry_whereDefined (ue)),
5571 size, filelocList_unparseUses (uses)));
5572 }
5573 }
5574 } end_usymtab_entries;
5575
5576 usymtab_shallowFree (copy);
5577}
5578
5579static /*@dependent@*/ /*@exposed@*/ usymtab
5580usymtab_getFileTab ()
5581 /*@globals filetab@*/
5582{
5583 llassert (filetab != NULL);
5584
5585 return filetab;
5586}
5587
5588/*@only@*/ cstring
5589usymtab_unparseStack ()
5590 /*@globals utab@*/
5591{
5592 return (usymtab_unparseStackTab (utab));
5593}
5594
5595static /*@only@*/ cstring
5596usymtab_unparseStackTab (usymtab t)
5597{
5598 bool firstOne = TRUE;
5599 cstring ret = cstring_makeLiteral ("[");
5600
5601 while (t != GLOBAL_ENV)
5602 {
5603 if (firstOne)
5604 {
5605 ret = message ("%q %q", ret, usymtab_typeName (t));
5606 firstOne = FALSE;
5607 }
5608 else
5609 {
5610 ret = message ("%q, %q", ret, usymtab_typeName (t));
5611 }
5612 t = t->env;
5613 }
5614
5615 ret = message ("%q ]", ret);
5616 return ret;
5617}
5618
5619static /*@only@*/ cstring
5620usymtab_typeName (/*@notnull@*/ usymtab t)
5621{
5622 switch (t->kind)
5623 {
5624 case US_GLOBAL: return cstring_makeLiteral ("global");
5625 case US_NORMAL: return cstring_makeLiteral ("normal");
5626 case US_TBRANCH: return cstring_makeLiteral ("true");
5627 case US_FBRANCH: return cstring_makeLiteral ("false");
5628 case US_CBRANCH: return cstring_makeLiteral ("case");
5629 case US_SWITCH: return cstring_makeLiteral ("switch");
5630 }
5631
5632 BADEXIT;
5633}
5634
28bf4b0b 5635void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
616915dd 5636 /*@modifies utab@*/
5637{
28bf4b0b 5638 if (!sRef_similar (s, al))
616915dd 5639 {
28bf4b0b 5640 usymtab_addForceMustAlias (s, al);
616915dd 5641 }
5642}
5643
5644/*
5645** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5646*/
5647
28bf4b0b 5648void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
616915dd 5649 /*@modifies utab@*/
5650{
5651 if (sRef_isMeaningful (s)
5652 && sRef_isMeaningful (al)
5653 && !(sRef_isConst (s) || sRef_isConst (al))
5654 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5655 {
5656 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5657 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5658
5659 /*
5660 ** for local variable, aliasing is symmetric
5661 */
5662
5663 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5664 {
5665 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5666 }
5667 }
5668 else
5669 {
5670 ;
5671 }
5672}
5673
5674void usymtab_clearAlias (sRef s)
5675 /*@modifies utab, s@*/
5676{
5677
5678 aliasTable_clearAliases (utab->aliases, s);
5679}
5680
5681sRefSet usymtab_allAliases (sRef s)
5682 /*@globals utab@*/
5683{
5684 if (sRef_isMeaningful (s))
5685 {
5686 sRefSet ret;
616915dd 5687
5688 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5689 aliasTable_canAlias (utab->aliases, s));
28bf4b0b 5690 return (ret);
616915dd 5691 }
5692 else
5693 {
28bf4b0b 5694 DPRINTF (("NOT A MEANINGFUL SREF!"));
616915dd 5695 return sRefSet_undefined;
5696 }
5697}
5698
5699/*@only@*/ sRefSet usymtab_canAlias (sRef s)
28bf4b0b 5700 /*@globals utab@*/
616915dd 5701{
5702 if (sRef_isMeaningful (s))
5703 {
5704 sRefSet res = aliasTable_canAlias (utab->aliases, s);
616915dd 5705 return res;
5706 }
28bf4b0b 5707
616915dd 5708 return sRefSet_undefined;
5709}
5710
5711/*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
28bf4b0b 5712 /*@globals utab@*/
616915dd 5713{
5714 return (aliasTable_aliasedBy (utab->aliases, s));
5715}
5716
5717/*@only@*/ cstring usymtab_unparseAliases ()
5718 /*@globals utab@*/
5719{
5720 return (aliasTable_unparse (utab->aliases));
5721}
5722
5723/*
5724** Debugging routines:
5725** okay to leak storage here, only for debugging
5726*/
5727
5728/*@-mustfree@*/
5729
5730void
5731usymtab_printOut (void)
5732 /*@globals utab@*/
5733{
5734 int i;
5735 usymtab s = utab;
5736 int depth = 0;
5737 char *ind = mstring_copy (" ");
5738
5739 fprintf (g_msgstream, "<<< [symbol table] >>>\n");
5740
5741 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5742 {
5743 cstring tname = usymtab_typeName (s);
5744
5745 if (depth < 5)
5746 {
5747 ind[depth * 3 + 1] = '\0';
5748 }
5749
5750 fprintf (g_msgstream, "level: %d (%s)\n", s->lexlevel,
5751 cstring_toCharsSafe (tname));
5752
5753 cstring_free (tname);
5754
5755 for (i = 0; i < s->nentries; i++)
5756 {
5757 cstring us = uentry_unparseFull (s->entries[i]);
5758 fprintf (g_msgstream, "%s\n", cstring_toCharsSafe (us));
5759 cstring_free (us);
5760 }
5761
5762 if (s->reftable != NULL && s->nentries > 0)
5763 {
5764 fprintf (g_msgstream, "\t<< Ref table >>\n");
5765
5766 for (i = 0; i < s->nentries; i++)
5767 {
5768 fprintf (g_msgstream, "\t%s %3d: %d, %d\n", ind, i,
5769 s->reftable[i]->level,
5770 s->reftable[i]->index);
5771 }
5772 }
5773
5774 ind[depth * 3 + 1] = ' ';
5775 depth++;
5776 s = s->env;
5777 }
5778 fprintf (g_msgstream, "<<< end usymtab >>>\n");
5779 mstring_free (ind);
5780 return;
5781}
5782
5783void
5784usymtab_printTypes ()
5785 /*@globals globtab@*/
5786{
5787 usymtab_printAllAux (globtab);
5788}
5789
5790void
5791usymtab_printAll (void)
5792 /*@globals utab@*/
5793{
5794 usymtab_printAllAux (utab);
5795}
5796
5797static void
5798usymtab_printAllAux (usymtab s)
5799 /*@modifies g_msgstream@*/
5800{
5801 int i;
5802 int depth = 0;
5803 char *ind = mstring_copy (" ");
5804
5805 printf ("[[[ usymtab ]]]");
5806
5807 while (s != GLOBAL_ENV)
5808 {
5809 if (depth < 5)
5810 ind[depth * 3 + 1] = '\0';
5811
5812 if (s->env == GLOBAL_ENV)
5813 {
5814 int looplow;
5815
5816 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5817 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5818 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5819
5820 looplow = 0;
5821
5822 for (i = looplow; i < s->nentries; i++)
5823 {
5824 printf ("%s%3d. %s\n", ind, i,
5825 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5826 }
5827 }
5828 else
5829 {
5830 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5831 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5832 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5833
5834 for (i = 0; i < s->nentries; i++)
5835 {
5836 printf ("%s%3d %s\n", ind, i,
5837 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5838 }
5839 }
5840
5841 ind[depth * 3 + 1] = ' ';
5842 depth++;
5843 s = s->env;
5844 }
5845 printf ("----------\n");
5846}
5847
5848void
5849usymtab_printComplete ()
5850 /*@globals utab@*/
5851{
5852 int i;
5853 int depth = 0;
5854 char *ind = mstring_copy (" ");
5855 usymtab s = utab;
5856
5857 while (s != GLOBAL_ENV)
5858 {
5859 if (depth < 5)
5860 {
5861 ind[depth * 3 + 1] = '\0';
5862 }
5863
5864 if (s->env == GLOBAL_ENV)
5865 {
5866 int looplow;
5867
5868 printf ("level: %d\n", s->lexlevel);
5869
5870 looplow = 0;
5871
5872 for (i = looplow; i < s->nentries; i++)
5873 {
5874 printf ("%s%3d %s\n", ind, i,
5875 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5876 }
5877 }
5878 else
5879 {
5880 printf ("level: %d\n", s->lexlevel);
5881 for (i = 0; i < s->nentries; i++)
5882 {
5883 printf ("%s%3d %s\n", ind, i,
5884 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5885 }
5886 }
5887
5888 ind[depth * 3 + 1] = ' ';
5889 depth++;
5890 s = s->env;
5891 }
5892
5893 printf ("----------\n");
5894 mstring_free (ind);
5895}
5896
3e3ec469 5897# ifdef S_SPLINT_S
616915dd 5898static /*@only@*/ cstring /*@unused@*/
5899usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5900{
5901 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5902 int i;
5903
5904 for (i = 0; i < s->nentries; i++)
5905 {
5906 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5907 }
5908
5909 c = message ("%q\n=========", c);
5910 return (c);
5911}
5912
5913static cstring /*@unused@*/ /*@only@*/
5914usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5915{
5916 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5917 bool_unparse (s->mustBreak),
5918 exitkind_unparse (s->exitCode));
5919 int i;
5920
5921 for (i = 0; i < s->nentries; i++)
5922 {
5923 sRef sr = uentry_getSref (s->entries[i]);
5924
5925 if (i == 0)
5926 {
5927 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
5928 sRef_isStateDefined (sr));
5929 }
5930 else
5931 {
5932 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
5933 sRef_isStateDefined (sr));
5934 }
5935
5936 }
5937
5938 return (c);
5939}
8250fa4a 5940# endif
616915dd 5941
5942void
5943usymtab_printLocal (void)
5944 /*@globals utab@*/
5945{
5946 int i;
5947 usymtab s = utab;
5948
5949 printf ("lexlevel: %d\n", s->lexlevel);
5950
5951 for (i = 0; i < s->nentries; i++)
5952 {
5953 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5954 }
5955
5956 while (s->lexlevel > 1)
5957 {
5958 s = s->env;
5959 }
5960
5961 llassert (usymtab_isDefined (s));
5962
5963 printf ("Params:\n");
5964
5965 for (i = 0; i < s->nentries; i++)
5966 {
5967 printf ("%d: %s\n", i,
5968 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5969 }
5970}
5971/*@=mustfree@*/
5972
5973static bool checkDistinctExternalName (uentry e)
5974 /*@globals globtab@*/
5975 /*@modifies *g_msgstream@*/
5976{
abd7f895 5977 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
616915dd 5978 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
5979 bool gotone = FALSE;
5980 bool extras = FALSE;
5981 bool hasError = FALSE;
5982 cstring name = uentry_rawName (e);
5983 usymtab st = globtab;
5984
5985 if (checklen == 0)
5986 {
5987 ;
5988 }
5989 else
5990 {
5991 if (uentry_isAnyTag (e))
5992 {
5993 checklen++; /* the tag marker doesn't count */
5994 }
5995 }
5996
5997 usymtab_entries (st, oe)
5998 {
5999 if (uentry_sameObject (oe, e))
6000 {
6001 continue;
6002 }
6003
6004 if (checklen == 0)
6005 {
6006 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6007 {
6008 if (gotone)
6009 {
6010 extras = TRUE;
6011 break;
6012 }
6013
6014 if (optgenerror
6015 (FLG_DISTINCTEXTERNALNAMES,
6016 message
6017 ("External identifier %q is not distinguishable from %q "
6018 "because alphabetical case is ignored",
6019 uentry_getName (e),
6020 uentry_getName (oe)),
6021 uentry_whereLast (e)))
6022 {
6023 uentry_showWhereAny (oe);
6024 uentry_setHasNameError (oe);
6025 gotone = TRUE;
6026 }
6027 }
6028 }
6029 else
6030 {
6031 if (ignorecase)
6032 {
6033 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6034 name, checklen))
6035 {
6036 if (gotone)
6037 {
6038 extras = TRUE;
6039 break;
6040 }
6041
6042 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6043 {
6044 if (optgenerror
6045 (FLG_DISTINCTEXTERNALNAMES,
6046 /*@-sefparams@*/
6047 message
6048 ("External identifier %q is not distinguishable from %q "
6049 "in the first %d characters (%q)",
6050 uentry_getName (e),
6051 uentry_getName (oe),
abd7f895 6052 size_toInt (checklen),
616915dd 6053 cstring_clip (uentry_getName (e), checklen)),
6054 /*@=sefparams@*/
6055 uentry_whereLast (e)))
6056 {
6057 uentry_showWhereAny (oe);
6058 uentry_setHasNameError (oe);
6059 gotone = TRUE;
6060 }
6061 }
6062 else
6063 {
6064 if (gotone)
6065 {
6066 extras = TRUE;
6067 break;
6068 }
6069
6070 if (optgenerror
6071 (FLG_DISTINCTEXTERNALNAMES,
6072 message
6073 ("External identifier %q is not distinguishable from %q "
6074 "in the first %d characters because alphabetical case "
6075 "is ignored",
6076 uentry_getName (e),
6077 uentry_getName (oe),
abd7f895 6078 size_toInt (checklen)),
616915dd 6079 uentry_whereLast (e)))
6080 {
6081 uentry_showWhereAny (oe);
6082 uentry_setHasNameError (oe);
6083 gotone = TRUE;
6084 }
6085 }
6086 }
6087 }
6088 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6089 {
6090 if (gotone)
6091 {
6092 extras = TRUE;
6093 break;
6094 }
6095
6096 if (optgenerror
6097 (FLG_DISTINCTEXTERNALNAMES,
6098 /*@-sefparams@*/
6099 message
6100 ("External identifier %q is not distinguishable from %q "
6101 "in the first %d characters (%q)",
6102 uentry_getName (e),
6103 uentry_getName (oe),
abd7f895 6104 size_toInt (checklen),
616915dd 6105 cstring_clip (uentry_getName (e), checklen)),
6106 /*@=sefparams@*/
6107 uentry_whereLast (e)))
6108 {
6109 uentry_showWhereAny (oe);
6110 uentry_setHasNameError (oe);
6111 gotone = TRUE;
6112 }
6113 }
6114 else
6115 {
6116 ; /* okay */
6117 }
6118 }
6119 } end_usymtab_entries ;
6120
6121 hasError = gotone;
6122
6123 if (extras)
6124 {
6125 llgenindentmsgnoloc
6126 (cstring_makeLiteral ("One or more additional "
6127 "indistinguishable external "
6128 "names not reported"));
6129 }
6130
6131 return hasError;
6132}
6133
6134static bool checkDistinctInternalName (uentry e)
6135 /*@globals utab@*/
6136 /*@modifies *g_msgstream@*/
6137{
6138 usymtab ttab = utab;
6139 cstring name = uentry_rawName (e);
abd7f895 6140 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
616915dd 6141 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6142 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6143
6144 if (uentry_isAnyTag (e) && (numchars != 0))
6145 {
6146 numchars++; /* the tag marker doesn't count */
6147 }
6148
6149 while (usymtab_isDefined (ttab))
6150 {
6151 usymtab_entries (ttab, oe)
6152 {
6153 if (uentry_sameObject (oe, e))
6154 {
6155 /*@innercontinue@*/ continue;
6156 }
6157
6158 switch (cstring_genericEqual
6159 (name, uentry_rawName (oe),
6160 numchars, caseinsensitive, lookalike))
6161 {
6162 case CGE_DISTINCT: /* okay */
6163 /*@switchbreak@*/
6164 break;
6165 case CGE_SAME:
6166 if (cstring_equal (name, uentry_rawName (oe)))
6167 {
6168 ; /* got a shadow error */
6169 }
6170 else
6171 {
6172 if (optgenerror
6173 (FLG_DISTINCTINTERNALNAMES,
6174 /*@-sefparams@*/
6175 message
6176 ("Internal identifier %q is not distinguishable from %q "
6177 "in the first %d characters (%q)",
6178 uentry_getName (e),
6179 uentry_getName (oe),
abd7f895 6180 size_toInt (numchars),
616915dd 6181 cstring_clip (uentry_getName (e), numchars)),
6182 /*@=sefparams@*/
6183 uentry_whereLast (e)))
6184 {
6185 uentry_showWhereAny (oe);
6186 uentry_setHasNameError (oe);
6187 return TRUE;
6188 }
6189 }
6190 /*@switchbreak@*/
6191 break;
6192 case CGE_CASE:
abd7f895 6193 if (numchars == 0 || (cstring_length (name) <= numchars))
616915dd 6194 {
6195 if (optgenerror
6196 (FLG_DISTINCTINTERNALNAMES,
6197 message
6198 ("Internal identifier %q is not distinguishable from %q "
6199 "without case sensitivity",
6200 uentry_getName (e),
6201 uentry_getName (oe)),
6202 uentry_whereLast (e)))
6203 {
6204 uentry_showWhereAny (oe);
6205 uentry_setHasNameError (oe);
6206 return TRUE;
6207 }
6208 }
6209 else
6210 {
6211 if (optgenerror
6212 (FLG_DISTINCTINTERNALNAMES,
6213 message
6214 ("Internal identifier %q is not distinguishable from %q "
6215 "in the first %d characters without case sensitivity",
6216 uentry_getName (e),
6217 uentry_getName (oe),
abd7f895 6218 size_toInt (numchars)),
616915dd 6219 uentry_whereLast (e)))
6220 {
6221 uentry_showWhereAny (oe);
6222 uentry_setHasNameError (oe);
6223 return TRUE;
6224 }
6225 }
6226 /*@switchbreak@*/
6227 break;
6228 case CGE_LOOKALIKE:
6229 if (numchars == 0
6230 || (cstring_length (name) <= numchars))
6231 {
6232 if (optgenerror
6233 (FLG_DISTINCTINTERNALNAMES,
6234 message
6235 ("Internal identifier %q is not distinguishable from %q "
6236 "except by lookalike characters",
6237 uentry_getName (e),
6238 uentry_getName (oe)),
6239 uentry_whereLast (e)))
6240 {
6241 uentry_showWhereAny (oe);
6242 uentry_setHasNameError (oe);
6243 return TRUE;
6244 }
6245 }
6246 else
6247 {
6248 if (optgenerror
6249 (FLG_DISTINCTINTERNALNAMES,
6250 message
6251 ("Internal identifier %q is not distinguishable from %q "
6252 "in the first %d characters except by lookalike characters",
6253 uentry_getName (e),
6254 uentry_getName (oe),
abd7f895 6255 size_toInt (numchars)),
616915dd 6256 uentry_whereLast (e)))
6257 {
6258 uentry_showWhereAny (oe);
6259 uentry_setHasNameError (oe);
6260 return TRUE;
6261 }
6262 }
6263 }
6264 } end_usymtab_entries ;
6265
6266 ttab = ttab->env;
6267 }
6268
6269 return FALSE;
6270}
6271
6272void usymtab_checkDistinctName (uentry e, int scope)
6273 /*@globals utab, globtab@*/
6274{
6275 bool hasError = FALSE;
6276 fileloc where = uentry_whereLast (e);
6277
6278 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6279 {
6280 if (scope == globScope)
6281 {
6282 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6283 {
6284 hasError = checkDistinctExternalName (e);
6285 }
6286 }
6287
6288 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6289 {
6290 hasError = checkDistinctInternalName (e);
6291 }
6292 }
6293
6294 if (hasError)
6295 {
28bf4b0b 6296 uentry_setHasNameError (e);
616915dd 6297 }
6298}
6299
28bf4b0b 6300/*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6301{
6302 uentry ue;
6303
6304 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6305 llassert (uentry_isValid (ue));
6306
6307 return uentry_getSref (ue);
6308}
6309
This page took 1.09775 seconds and 5 git commands to generate.