]> andersk Git - splint.git/blame - src/usymtab.c
Fixed state clauses. Added obvious loop exec checking.
[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**
20** For information on lclint: lclint-request@cs.virginia.edu
21** To report a bug: lclint-bug@cs.virginia.edu
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
49# include "lclintMacros.nf"
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
196static /*@falsenull@*/ bool usymtab_isBranch (usymtab u)
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
761 DPRINTF (("Using symtab: %s", usymtab_unparseLocalAux (st)));
762
763 eindex = usymtab_getIndex (st, ename);
764
765 if (eindex != NOT_FOUND)
766 {
767 uentry ce = st->entries[eindex];
28bf4b0b 768
616915dd 769 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
770
771 if (uentry_isPriv (ce)
772 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
773 || (uentry_isStatic (ce)
774 && uentry_isAnyTag (ce)
775 && (uentry_isDeclared (ce)
776 && !fileloc_sameFile (uentry_whereDefined (ce),
777 uentry_whereDefined (e)))))
778 {
779 /*
780 ** overload entry
781 ** if overloading import should do some checks!
782 */
783
784 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
785
28bf4b0b 786 DPRINTF (("Overloading!"));
787
616915dd 788 st->entries[eindex] = e;
789
790 if (uentry_isDatatype (e))
791 {
792 uentry_setDatatype (e, eindex);
793 }
794
795 if (st == globtab && !uentry_isSpecified (e))
796 {
797 exprChecks_checkExport (e);
798 }
799
28bf4b0b 800 if (cstringTable_isDefined (st->htable))
616915dd 801 {
28bf4b0b 802 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
803 cstring_copy (uentry_rawName (e)));
616915dd 804 }
805
806 uentry_free (ce);
807 ce = e;
808 }
809 else if (uentry_isSpecified (ce))
810 {
811 if (uentry_isSpecified (e))
812 {
28bf4b0b 813 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
814
616915dd 815 if (fileloc_isImport (uentry_whereSpecified (ce)))
28bf4b0b 816 {
817 if (cstringTable_isDefined (st->htable))
616915dd 818 {
28bf4b0b 819 cstringTable_replaceKey (st->htable,
820 uentry_rawName (ce),
821 cstring_copy (uentry_rawName (e)));
616915dd 822 }
823
824 uentry_free (ce);
825 st->entries[eindex] = e;
826 ce = e;
827
828 if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
829 }
830 else
831 {
832 if (fileloc_isImport (uentry_whereSpecified (e)))
833 {
834 uentry_free (e);
835 }
836 else
837 {
28bf4b0b 838 /* Respecification errors already reported */
839 DPRINTF (("Respecification: %s / %s",
840 fileloc_unparse (uentry_whereSpecified (e)),
841 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
842
616915dd 843 if (uentry_isDatatype (e))
844 {
845 uentry_setDatatype (e, eindex);
846 }
847
28bf4b0b 848 if (cstringTable_isDefined (st->htable))
616915dd 849 {
28bf4b0b 850 cstringTable_replaceKey (st->htable,
851 uentry_rawName (ce),
852 cstring_copy (uentry_rawName (e)));
616915dd 853 }
854
855 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
856 uentry_free (ce);
857 st->entries[eindex] = e;
858 ce = e;
859 }
860 }
861 }
862 else /* e not specified */
863 {
28bf4b0b 864 DPRINTF (("Merging..."));
865
616915dd 866 if (uentry_isDeclared (ce))
867 {
1d239d69 868 /* evans 2001-08-26
869 No - this can happen for internal typedefs
870 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
871 */
872
28bf4b0b 873 DPRINTF (("Merge defn"));
616915dd 874 uentry_mergeDefinition (ce, e);
875 }
876 else
877 {
1d239d69 878 /* evans 2001-08-26
879 No - this can happen for internal typedefs
880 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
881 */
882
28bf4b0b 883 DPRINTF (("Merge entries..."));
616915dd 884 uentry_mergeEntries (ce, e);
28bf4b0b 885 DPRINTF (("After: %s", uentry_unparseFull (ce)));
616915dd 886 }
887 }
888 }
889 else /* ce not specified */
890 {
891 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
892 {
893 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
894 || uentry_isEnumConstant (e))
895 {
896 ; /*
897 ** Not a bug. Code like,
898 ** int f (void) { typedef int tint; ... }
899 ** is legal.
900 */
901 }
902 else
903 {
904 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
905 "(lexlevel = %d, modFunction = %s) adding: %q",
906 st->lexlevel, bool_unparse (sRef_modInFunction ()),
907 uentry_unparse (e)));
908
909 if (sRef_modInFunction ())
910 {
911 /* make sure the sRef is not bashed! */
912 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
913 }
914 }
915 }
916
28bf4b0b 917 DPRINTF (("Merge.."));
616915dd 918 uentry_mergeDefinition (ce, e);
919 }
920
921 if (isSref)
922 {
923 ctype ct = uentry_getType (ce);
924
925 if (uentry_isFunction (ce) && ctype_isFunction (ct))
926 {
28bf4b0b 927 ct = ctype_getReturnType (ct);
616915dd 928 }
929
6970c11b 930 uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct, stateInfo_makeLoc (uentry_whereLast (ce))));
931 }
616915dd 932 }
933 else /* no previous entry */
934 {
935 uentry outer;
936
937 if (st->lexlevel == globScope
938 && !uentry_isStatic (e)
939 && !uentry_isExtern (e)
940 && usymtab_isDefined (filetab))
941 {
942 /*
943 ** check if there is a static entry: (i.e.,
944 **
945 ** static int f ();
946 ** ...
947 ** int f ();
948 */
949
950 eindex = usymtab_getIndex (filetab, ename);
951
952 if (eindex != NOT_FOUND)
953 {
954 uentry ce = filetab->entries[eindex];
955
956 uentry_setStatic (e);
957 uentry_mergeDefinition (ce, e);
958 staticEntry = TRUE;
959 goto exitPoint;
960 }
961 }
962
963 outer = usymtab_lookupQuiet (st->env, ename);
964
7ebcc5bb 965 DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
966 DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
967
616915dd 968 /*
969 ** no previous definition, add the new one
970 */
971
972 if (!noshadowerror
973 && uentry_isValid (outer)
974 && !(uentry_isYield (e) || uentry_isYield (outer))
975 && fileloc_isDefined (uentry_whereLast (e))
ccf0a4a8 976 && !fileloc_isXHFile (uentry_whereLast (e))
977 && fileloc_isDefined (uentry_whereLast (outer))
978 && !fileloc_isXHFile (uentry_whereLast (outer)))
616915dd 979 {
980 if (!uentry_sameKind (outer, e))
981 {
982 ; /* no error */
983 }
984 else
985 {
986 if (ctype_isUnknown (uentry_getType (outer))
987 || uentry_isForward (outer))
988 {
989 ;
990 }
991 else
992 {
993 if (optgenerror
994 (FLG_SHADOW,
995 message ("%s %q shadows outer declaration",
996 ekind_capName (uentry_getKind (e)),
997 uentry_getName (e)),
998 uentry_whereLast (e)))
999 {
1000 uentry_showWhereLast (outer);
1001 }
1002 }
1003 }
1004 }
1005
1006 if (st == globtab && context_getFlag (FLG_NEWDECL))
1007 {
1008 voptgenerror
1009 (FLG_NEWDECL,
1010 message ("New declaration: %q", uentry_getName (e)),
1011 uentry_whereLast (e));
1012 }
1013
1014 eindex = usymtab_addEntryAux (st, e, isSref);
1015 }
1016
1017 exitPoint:
1018 return (staticEntry ? USYMIDINVALID : eindex);
1019}
1020
1021# ifndef NOLCL
1022static void
1023usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
1024 /*@globals globtab@*/ /*@modifies st, e@*/
1025{
1026 cstring ename = uentry_rawName (e);
1027 int eindex;
1028
1029 /* static tags in global scope */
1030 eindex = usymtab_getIndex (st, ename);
1031
1032 if (eindex != NOT_FOUND)
1033 {
1034 uentry ce = st->entries[eindex];
1035
28bf4b0b 1036 if (cstringTable_isDefined (st->htable))
616915dd 1037 {
28bf4b0b 1038 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1039 cstring_copy (uentry_rawName (e)));
616915dd 1040 }
1041
1042 uentry_free (ce);
1043 st->entries[eindex] = e;
1044 }
1045 else
1046 {
1047 eindex = usymtab_addEntryAux (st, e, FALSE);
1048 }
1049}
1050# endif
1051
1052/*@=deparrays@*/
1053
1054void usymtab_supEntry (uentry e)
1055 /*@globals utab, filetab, globtab@*/
1056 /*@modifies utab, globtab, e@*/
1057{
1058 (void) usymtab_supEntryAux (utab, e, FALSE);
1059}
1060
1061/*
1062** this should be lots more efficient!
1063*/
1064
1065static /*@exposed@*/ uentry
1066 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1067 /*@only@*/ uentry e, bool isref)
1068 /*@globals globtab, filetab@*/
1069 /*@modifies tab, globtab, e@*/
1070{
1071 cstring rawName = cstring_copy (uentry_rawName (e));
1072 bool stat = (tab == globtab) && uentry_isStatic (e);
1073 uentry ret;
1074
616915dd 1075 (void) usymtab_supEntryAux (tab, e, isref);
1076
1077 if (stat)
1078 {
1079 ret = usymtab_lookupAux (filetab, rawName);
1080 }
1081 else
1082 {
1083 ret = usymtab_lookupAux (tab, rawName);
1084
1085 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1086 {
1087 ret = usymtab_lookupAux (filetab, rawName);
1088 }
1089 }
1090
1091 cstring_free (rawName);
1092 return ret;
1093}
1094
1095/*@dependent@*/ /*@exposed@*/ uentry
1096 usymtab_supEntryReturn (/*@only@*/ uentry e)
1097 /*@globals utab, filetab, globtab@*/
1098 /*@modifies utab, globtab, e@*/
1099{
1100 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1101}
1102
1103/*@dependent@*/ /*@exposed@*/ uentry
1104 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1105 /*@globals utab, globtab, filetab@*/
1106 /*@modifies utab, globtab, e@*/
1107{
1108 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1109}
1110
1111/*@dependent@*/ /*@exposed@*/ uentry
1112 usymtab_supGlobalEntryReturn (uentry e)
1113 /*@globals globtab, filetab@*/
1114 /*@modifies globtab, e@*/
1115{
1116 uentry ret;
1117
1118 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1119
7ebcc5bb 1120 /*
1121 ** We need to keep track of internal function declarations, so
1122 ** we can remove them from the symbol table after exiting this
1123 ** function. This is a bit bogus, of course.
1124 */
1125
616915dd 1126 if (sRef_modInFunction ())
1127 {
1128 recordFunctionType (ret);
1129 }
1130
1131 return (ret);
1132}
1133
1134ctype
1135usymtab_supTypeEntry (/*@only@*/ uentry e)
1136 /*@globals globtab, filetab@*/
1137 /*@modifies globtab, e@*/
1138{
1139 usymId uid;
1140 ctype ret;
1141
1142 if (uentry_isAbstractDatatype (e))
1143 {
1144 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1145 ret = ctype_createAbstract (uid);
1146 }
1147 else
1148 {
1149 uid = usymtab_supEntryAux (globtab, e, FALSE);
1150 ret = ctype_createUser (uid);
1151 }
1152
1153 if (sRef_modInFunction ())
1154 {
1155 recordFunctionType (globtab->entries[uid]);
1156 }
1157
1158 return ret;
1159}
1160
1161uentry
1162usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1163 /*@globals globtab, filetab@*/
1164 /*@modifies globtab@*/
1165{
1166 usymId uid;
28bf4b0b 1167
1168 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1169
616915dd 1170 if (uentry_isAbstractDatatype (e))
1171 {
1172 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1173 }
28bf4b0b 1174 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1175 {
1176 bool maybeabs = TRUE;
1177 cstring sname = uentry_getName (e);
1178 uentry ue = usymtab_lookupGlobSafe (sname);
1179 cstring_free (sname);
1180
1181 if (uentry_isValid (ue))
1182 {
1183 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1184
1185 if (uentry_isDatatype (ue))
1186 {
1187 if (uentry_isMaybeAbstract (ue))
1188 {
1189 ;
1190 }
1191 else
1192 {
1193 maybeabs = FALSE;
1194 }
1195 }
1196 else
1197 {
1198 DPRINTF (("Not datatype!"));
1199 }
1200 }
1201
1202 if (maybeabs)
1203 {
1204 uentry ux;
1205 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1206 ux = usymtab_getTypeEntry (uid);
1207 uentry_setAbstract (ux);
1208 }
1209 else
1210 {
1211 uid = usymtab_supEntryAux (globtab, e, FALSE);
1212 e = usymtab_getTypeEntry (uid);
1213
1214 if (uentry_isMaybeAbstract (e))
1215 {
1216 uentry_setConcrete (e);
1217 }
1218 }
1219 }
616915dd 1220 else
1221 {
1222 uid = usymtab_supEntryAux (globtab, e, FALSE);
28bf4b0b 1223 e = usymtab_getTypeEntry (uid);
1224
1225 if (uentry_isMaybeAbstract (e))
1226 {
1227 uentry_setConcrete (e);
1228 }
616915dd 1229 }
1230
1231 if (sRef_modInFunction ())
1232 {
1233 recordFunctionType (globtab->entries[uid]);
1234 }
1235
1236 return (globtab->entries[uid]);
1237}
1238
1239usymId
1240usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1241 /*@globals globtab, filetab@*/
1242 /*@modifies globtab, e@*/
1243{
1244 usymId uid;
28bf4b0b 1245 uentry ue;
1246
616915dd 1247 uid = usymtab_supEntryAux (globtab, e, FALSE);
28bf4b0b 1248 ue = usymtab_getTypeEntry (uid);
616915dd 1249
1250 if (dodef)
1251 {
616915dd 1252 uentry_setDatatype (ue, uid);
1253 }
1254
28bf4b0b 1255 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
616915dd 1256 {
1257 context_addFileAccessType (uid);
1258 }
1259
1260 if (sRef_modInFunction ())
1261 {
1262 recordFunctionType (globtab->entries[uid]);
1263 }
1264
1265 return (uid);
1266}
1267
1268# ifndef NOLCL
1269usymId
1270usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1271 /*@globals globtab, filetab@*/
1272 /*@modifies globtab, e@*/
1273{
1274 usymId uid;
1275
1276 uid = usymtab_supEntryAux (globtab, e, FALSE);
1277
1278 if (dodef)
1279 {
1280 uentry ue = usymtab_getTypeEntry (uid);
1281
1282 uentry_setDatatype (ue, uid);
1283 }
1284
1285 if (sRef_modInFunction ())
1286 {
1287 recordFunctionType (globtab->entries[uid]);
1288 }
1289
1290 return (uid);
1291}
1292# endif
1293
1294ctype
1295usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1296 /*@globals globtab, filetab@*/
1297 /*@modifies globtab, e@*/
1298{
1299 usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1300 uentry ue = usymtab_getTypeEntry (uid);
1301
1302 uentry_setDatatype (ue, uid);
1303
1304 if (sRef_modInFunction ())
1305 {
1306 recordFunctionType (globtab->entries[uid]);
1307 }
1308
1309 return (uentry_getAbstractType (ue));
1310}
1311
1312void
1313 usymtab_supEntrySref (uentry e)
1314 /*@globals utab, globtab, filetab@*/
1315 /*@modifies utab, globtab, e@*/
1316{
1317 sRef old = uentry_getSref (e);
1318
1319
1320 if (sRef_isType (old))
1321 {
1322 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1323
1324 /*@access uentry@*/
1325 if (uentry_isValid (ue))
1326 {
1327 sRef uref = uentry_getSref (ue);
1328
1329 sRef_mergeStateQuiet (uref, old);
1330 sRef_clearDerived (uref);
1331 }
1332 /*@noaccess uentry@*/
1333 }
1334 else if (sRef_isKnown (old))
1335 {
1336 usymtab_supEntry (e);
1337 }
1338 else
1339 {
1340 (void) usymtab_supEntryAux (utab, e, TRUE);
1341 }
1342}
1343
1344void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1345 /*@globals globtab, filetab@*/
1346 /*@modifies globtab, filetab, e@*/
1347{
1348 usymId uid;
1349
1350 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1351
1352 uid = usymtab_supEntryAux (globtab, e, FALSE);
1353
1354 if (sRef_modInFunction ())
1355 {
1356 recordFunctionType (globtab->entries[uid]);
1357 }
1358}
1359
1360uentry
1361 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1362 /*@globals filetab, globtab@*/
1363 /*@modifies filetab, globtab, e@*/
1364{
1365 llassert (filetab != usymtab_undefined);
1366 DPRINTF (("File entry: %s", uentry_unparse (e)));
1367 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1368}
1369
1370/*
1371** observers
1372*/
1373
1374bool
1375usymtab_inDeepScope () /*@globals utab@*/
1376{
1377 return (utab->lexlevel > paramsScope);
1378}
1379
1380static int
1381usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1382{
1383 int i;
1384
28bf4b0b 1385 DPRINTF (("Lookup %s", k));
616915dd 1386
28bf4b0b 1387 if (cstringTable_isDefined (s->htable))
1388 {
1389 i = cstringTable_lookup (s->htable, k);
616915dd 1390 return i;
1391 }
1392 else
1393 {
1394 for (i = 0; i < s->nentries; i++)
1395 {
1396 uentry current = s->entries[i];
1397
28bf4b0b 1398 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1399
616915dd 1400 if (!uentry_isUndefined (current)
1401 && cstring_equal (uentry_rawName (current), k))
1402 {
1403 return i;
1404 }
1405 }
1406
1407 return NOT_FOUND;
1408 }
1409}
1410
1411static uentry
1412usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1413{
1414 llassert (i >= 0 && i < s->nentries);
1415 return (s->entries[i]);
1416}
1417
1418usymId
1419usymtab_getTypeId (cstring k) /*@globals globtab@*/
1420{
1421 usymId uid = usymtab_getIndex (globtab, k);
1422
1423 if (uid == NOT_FOUND) return USYMIDINVALID;
1424
1425 if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
1426 return USYMIDINVALID;
1427 }
1428
1429 return uid;
1430}
1431
1432/*@dependent@*/ uentry
1433usymtab_lookupStructTag (cstring k)
1434{
1435 cstring sname = makeStruct (k);
1436 uentry ue = usymtab_lookupGlob (sname);
28bf4b0b 1437
1438 cstring_free (sname);
616915dd 1439 return (ue);
1440}
1441
1442/*@dependent@*/ uentry
1443usymtab_lookupUnionTag (cstring k)
1444{
1445 cstring uname = makeUnion (k);
1446 uentry res = usymtab_lookupGlob (uname);
1447
1448 cstring_free (uname);
1449 return res;
1450}
1451
1452/*@dependent@*/ uentry
1453usymtab_lookupEnumTag (cstring k)
1454{
1455 cstring ename = makeEnum (k);
1456 uentry res = usymtab_lookupGlob (ename);
1457
1458 cstring_free (ename);
1459 return res;
1460}
1461
1462usymId
1463usymtab_getId (cstring k) /*@globals globtab@*/
1464{
1465 usymId uid = usymtab_getIndex (globtab, k);
1466 uentry ue;
1467
1468 if (uid == NOT_FOUND)
1469 {
1470 return USYMIDINVALID;
1471 }
1472
1473 ue = usymtab_getGlobalEntry (uid);
1474
1475 if (uentry_isPriv (ue))
1476 {
1477 return USYMIDINVALID;
1478 }
1479
1480 return uid;
1481}
1482
1483static /*@exposed@*/ uentry
1484usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1485{
1486 llassert (uid != USYMIDINVALID);
1487
1488 if (uid < 0 || uid >= s->nentries)
1489 {
1490 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1491 s->lexlevel, uid));
1492 return uentry_undefined;
1493 }
1494
1495 llassertprint (uentry_isValid (s->entries[uid]),
1496 ("entry undefined: %d", uid));
1497
1498 return s->entries[uid];
1499}
1500
1501/*@dependent@*/ /*@observer@*/ uentry
1502 usymtab_getGlobalEntry (usymId uid)
1503 /*@globals utab, globtab@*/
1504{
1505 if (dbgfree) return (uentry_undefined);
1506
1507 if (utab->lexlevel > paramsScope)
1508 {
1509 /* need to do this the awkward way, since it could be in conditional scope */
1510 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1511 }
1512 else
1513 {
1514 return (globtab->entries[uid]);
1515 }
1516}
1517
1518/*@dependent@*/ /*@exposed@*/ uentry
1519 usymtab_getTypeEntry (usymId uid)
1520 /*@globals globtab@*/
1521{
1522 if (dbgload)
1523 {
1524 if (uid >= 0 && uid < globtab->nentries)
1525 {
1526 return (globtab->entries[uid]);
1527 }
1528 else
1529 {
1530 return (uentry_undefined);
1531 }
1532 }
1533 else
1534 {
28bf4b0b 1535 llassert (uid >= 0 && uid < globtab->nentries);
616915dd 1536 return (globtab->entries[uid]);
1537 }
1538}
1539
1540/*
1541** in load files
1542*/
1543
1544/*@dependent@*/ /*@exposed@*/ uentry
1545 usymtab_getTypeEntrySafe (usymId uid)
1546 /*@globals globtab@*/
1547{
1548 if (uid < 0 || uid >= globtab->nentries)
1549 {
1550 return uentry_undefined;
1551 }
1552
1553 return (globtab->entries[uid]);
1554}
1555
1556bool
1557 usymtab_isBoolType (usymId uid)
1558 /*@globals globtab@*/
1559{
1560 llassert (uid >= 0 && uid < globtab->nentries);
1561
1562 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1563 context_getBoolName ()));
1564}
1565
1566cstring
1567usymtab_getTypeEntryName (usymId uid)
1568 /*@globals globtab@*/
1569{
1570 uentry ue;
1571
1572 if (dbgfree)
1573 {
1574 return (cstring_makeLiteral ("<freetype>"));
1575 }
1576
1577 ue = usymtab_getTypeEntry (uid);
1578
1579 if (dbgload && !uentry_isValid (ue))
1580 {
1581 return (message ("<missing type: %d>", uid));
1582 }
1583
1584 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1585
1586 return (uentry_getName (ue));
1587}
1588
8250fa4a 1589# if 0
28bf4b0b 1590/*@unused@*/ static void
616915dd 1591usymtab_rehash (/*@notnull@*/ usymtab s)
1592{
1593 int i;
1594
28bf4b0b 1595 if (cstringTable_isDefined (s->htable))
616915dd 1596 {
28bf4b0b 1597 cstringTable_free (s->htable);
616915dd 1598 }
1599
28bf4b0b 1600 s->htable = cstringTable_create (LLHASHSIZE);
616915dd 1601
1602 for (i = 0; i < s->nentries; i++)
1603 {
28bf4b0b 1604 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
616915dd 1605 }
1606}
8250fa4a 1607# endif
616915dd 1608
1609/*
1610** superficial copy of usymtab
1611**
1612** DO copy spec entries
1613*/
1614
1615static /*@only@*/ /*@notnull@*/ usymtab
1616usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1617{
1618 usymtab copytab = usymtab_createRoot ();
1619 int i;
1620
1621 for (i = 0; i < s->nentries; i++)
1622 {
1623 usymtab_addEntryBase (copytab, s->entries[i]);
1624 }
1625
1626 return copytab;
1627}
1628
1629static void
1630usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1631{
1632 aliasTable_free (s->aliases);
1633 refTable_free (s->reftable, s->nentries);
1634 sfree (s->entries);
1635 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1636}
1637
1638/*
1639** converts usymId from old table to sorted one
1640*/
1641
1642usymId
1643 usymtab_convertId (usymId uid)
1644 /*@globals oldtab, utab@*/
1645{
1646 uentry ue;
1647 usymId ret;
1648 cstring name;
1649
1650 llassert (usymtab_isDefined (oldtab));
1651
1652 ue = usymtab_getEntryAux (oldtab, uid);
1653
1654 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1655
1656 name = uentry_rawName (ue);
1657
1658 ret = usymtab_getIndex (utab, name);
28bf4b0b 1659 llassert (ret == uid); /*! for now, no rehash! */
1660 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1661 uentry_unparse (ue), uid,
1662 uentry_unparse (utab->entries[ret]), ret));
616915dd 1663
1664 llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1665
1666 return (ret);
1667}
1668
1669void
1670usymtab_prepareDump (void)
1671 /*@globals oldtab, utab@*/
1672 /*@modifies oldtab, utab@*/
1673{
1674 llassert (usymtab_inGlobalScope ());
616915dd 1675 llassert (oldtab == usymtab_undefined);
1676
28bf4b0b 1677 /*
1678 DPRINTF (("Preparing to dump:"));
1679 usymtab_printAll ();
1680 */
1681
616915dd 1682 oldtab = usymtab_shallowCopy (utab);
1683
1684 /*
28bf4b0b 1685 ** alpha compare - make sure order is same on different platforms
1686 ** error messages appear in same order
616915dd 1687 */
1688
28bf4b0b 1689 /*
616915dd 1690 qsort (utab->entries, (size_t)utab->nentries,
28bf4b0b 1691 sizeof (*utab->entries),
1692 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1693
616915dd 1694 usymtab_rehash (utab);
28bf4b0b 1695 */
1696
1697 /*
1698 DPRINTF (("After rehash:"));
1699 usymtab_printAll ();
1700 */
616915dd 1701}
1702
28bf4b0b 1703void usymtab_dump (FILE *fout)
1704 /*@globals utab, oldtab@*/
616915dd 1705{
1706 int i;
1707 bool neednl = FALSE;
1708 uentry lastentry = uentry_undefined;
1709 ekind lastekind = KINVALID;
1710 int linelen = 0;
1711
1712 /*
1713 ** must call prepareDump first
1714 */
1715
1716 llassert (oldtab != usymtab_undefined);
1717
1718 for (i = 0; i < utab->nentries; i++)
1719 {
1720 uentry thisentry = utab->entries[i];
1721 ekind thisekind = uentry_getKind (thisentry);
1722
28bf4b0b 1723 if (!uentry_hasRealName (thisentry))
1724 {
1725 llassert (uentry_isGlobalMarker (thisentry));
1726
1727 if (neednl)
1728 {
1729 check (fputc ('\n', fout) == (int) '\n');
1730 }
1731
1732 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1733 lastekind = KINVALID;
1734 linelen = 0;
1735 neednl = FALSE;
1736 }
1737 else
1738 {
1739 if (thisekind != lastekind)
1740 {
1741 if (neednl)
1742 {
1743 check (fputc ('\n', fout) == (int) '\n');
1744 }
1745
1746 neednl = FALSE;
1747 lastentry = uentry_undefined;
1748 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1749 cstring_toCharsSafe (ekind_capName (thisekind)));
1750 lastekind = thisekind;
1751 linelen = 0;
1752 }
1753
1754 /*
1755 ** evans - 2001-02-18 - added the - 48 fudge factor...
1756 ** extra characters dumped, but I haven't counded them carefully...
1757 */
1758
1759 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1760 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1761 {
1762 cstring cdump;
1763
1764 DPRINTF (("Dumping entry: %d", i));
1765 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1766 /* was: cdump = uentry_dump (thisentry)); */
1767
1768 lastentry = thisentry;
1769 if (neednl)
1770 {
1771 check (fputc ('\n', fout) == (int) '\n');
1772 linelen = 0;
1773 }
1774
1775 linelen += cstring_length (cdump);
1776
1777 /* no new line here! */
1778 if (cstring_length (cdump) > 0)
1779 {
1780 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1781 }
1782
1783 cstring_free (cdump);
1784 neednl = TRUE;
1785 }
1786 else
1787 {
1788 cstring cdump = uentry_rawName (thisentry);
1789 DPRINTF (("Raw name: %s", cdump));
1790 linelen += (cstring_length (cdump) + 1);
1791 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1792 }
1793 }
616915dd 1794 }
1795
1796 if (neednl)
1797 {
1798 check (fputc ('\n', fout) == (int) '\n');
1799 }
920a3797 1800
1801 lastekind = KINVALID;
1802
1803 fprintf(fout, ";; Library constraints\n");
1804 for (i = 0; i < utab->nentries; i++)
1805 {
1806 uentry thisentry = utab->entries[i];
1807
1808 if (uentry_isFunction (thisentry) )
1809 {
1810 constraintList preconditions;
1811 constraintList postconditions;
1812
1813 preconditions = uentry_getFcnPreconditions (thisentry);
1814 postconditions = uentry_getFcnPostconditions (thisentry);
1815
1816 if ( constraintList_isDefined(preconditions) ||
1817 constraintList_isDefined(postconditions) )
1818 {
28bf4b0b 1819 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
920a3797 1820 if (constraintList_isDefined(preconditions) )
1821 {
1822 fprintf(fout,"pre:\n");
1823 constraintList_dump(preconditions, fout);
1824 fprintf (fout, ";; end precondition constraints\n" );
1825 constraintList_free(preconditions);
1826 }
1827 else
1828 {
1829 fprintf(fout,"pre:EMPTY\n");
1830 }
1831 if (constraintList_isDefined(postconditions) )
1832 {
1833 fprintf(fout,"post:\n");
1834 constraintList_dump(postconditions, fout);
1835 fprintf (fout, ";; end precondition constraints\n" );
1836 constraintList_free(postconditions);
1837 }
1838 else
1839 {
1840 fprintf(fout,"post:EMPTY\n");
1841 }
1842 }
1843
1844 }
1845 }
616915dd 1846}
1847
3e3ec469 1848
616915dd 1849void usymtab_load (FILE *f)
1850 /*@globals utab, globtab@*/
1851 /*@modifies utab, *f@*/
1852{
1853 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1854 char *os = s;
1855 ekind kind = KINVALID;
1856 fileloc loc = g_currentloc;
1857 char c;
1858 uentry ue;
1859
1860 dbgload = TRUE;
1861
1862 llassert (utab == globtab);
1863 llassert (utab->nentries == 0);
1864
28bf4b0b 1865 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
616915dd 1866 && *s == ';')
1867 {
28bf4b0b 1868 /* ignore ; comments */ ;
616915dd 1869 }
28bf4b0b 1870
616915dd 1871 while (s != NULL && *s != ';')
1872 {
28bf4b0b 1873 int index;
1874
616915dd 1875 if (*s == '*')
1876 {
28bf4b0b 1877 int ek;
616915dd 1878 s++;
28bf4b0b 1879 ek = reader_getInt (&s);
616915dd 1880
28bf4b0b 1881 if (ek == KGLOBALMARKER)
1882 {
1883 uentry lue = uentry_makeGlobalMarker ();
1884 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1885 usymtab_addEntryAlways (utab, lue);
1886 kind = KINVALID;
1887 goto nextiter;
1888 }
1889 else
1890 {
1891 kind = ekind_fromInt (ek);
1892 goto nextiter;
1893 }
616915dd 1894 }
1895
1896 if (*s == '$')
1897 {
1898 llfatalerror
1899 (cstring_makeLiteral
1900 ("Library is in obsolete format. Use lclint +whichlib "
1901 "to see which library is being loaded."));
1902 }
1903
28bf4b0b 1904 if (reader_optCheckChar (&s, '^'))
1905 {
1906 index = reader_getInt (&s);
1907 }
1908 else
1909 {
1910 index = -1;
1911 }
1912
1913 llassert (kind != KINVALID);
616915dd 1914 ue = uentry_undump (kind, loc, &s);
28bf4b0b 1915
1916 llassert (utab->nentries == index || index == -1);
616915dd 1917
1918 if (uentry_isValid (ue))
1919 {
28bf4b0b 1920 int lastindex = utab->nentries;
1921 ue = usymtab_addEntryAlways (utab, ue);
3e3ec469 1922
1923
1924# if 0
1925 if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */
1926 {
1927 cstring uname = uentry_getName (ue);
1928
1929 /* Also check its a macro... */
1930 DPRINTF (("Installing: %s", uname));
1931
1932 cpphash_installMacro
1933 (mstring_copy (cstring_toCharsSafe (uname)),
1934 cstring_length (uname),
1935 cpplib_createDefinition (message ("%s 255", uname),
1936 loc,
1937 FALSE, FALSE).defn,
1938 cpphash_hashCode (cstring_toCharsSafe (uname),
1939 cstring_length (uname),
1940 CPP_HASHSIZE));
1941
1942 DPRINTF (("After install: %s", uname));
1943 }
1944# endif
1945
28bf4b0b 1946 if (utab->nentries != lastindex + 1)
1947 {
1948 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1949 BADBRANCH;
1950 }
616915dd 1951 /*@-branchstate@*/
1952 }
1953 /*@=branchstate@*/
1954
1955 /*
1956 ** now, any other names are the same uentry
1957 */
1958
1959 while (*(s++) == '#')
1960 {
28bf4b0b 1961 cstring name = cstring_fromCharsO (reader_getWord (&s));
616915dd 1962 uentry nue = uentry_nameCopy (name, ue);
28bf4b0b 1963 /*
1964 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1965 BADBRANCH;
1966 */
616915dd 1967
28bf4b0b 1968 usymtab_addEntryAlways (utab, nue);
616915dd 1969 }
1970
1971 while ((c = *s) != '\0' && (c !='\n'))
1972 {
1973 if (c != ' ' || c != '\t')
1974 {
1975 llbuglit ("Junk in load file");
1976 }
1977
1978 s++;
1979 }
1980
1981 nextiter:
28bf4b0b 1982 {
1983 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
1984 }
616915dd 1985 }
1986
920a3797 1987 /*DRL added 6/21/01
1988 to handle reading of buffer overflow related constraints
1989 */
1990 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
1991 && *s == ';')
1992 {
1993 ; /* ignore ;-comments */
1994 }
1995
1996 while (s != NULL && *s != ';')
1997 {
1998 constraintList preconditions;
1999 constraintList postconditions;
2000
28bf4b0b 2001 cstring name = cstring_fromChars(reader_getWord(&s) );
920a3797 2002 cstring temp;
2003 ue = usymtab_lookup ( name );
2004
2005 cstring_free(name);
2006
2007 preconditions = constraintList_undefined;
2008 postconditions = constraintList_undefined;
2009
2010 if (!uentry_isValid(ue) )
2011 {
28bf4b0b 2012 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
920a3797 2013 }
2014 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2015
ccf0a4a8 2016 temp = cstring_fromChars (reader_getWord(&s) );
920a3797 2017
28bf4b0b 2018 if (cstring_compareLit (temp,"pre:") == 0 )
920a3797 2019 {
3814599d 2020 preconditions = constraintList_undump (f);
920a3797 2021 }
28bf4b0b 2022 else
2023 {
2024 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2025 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2026 }
2027
920a3797 2028 cstring_free(temp);
2029
2030 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2031
28bf4b0b 2032 temp = cstring_fromChars(reader_getWord(&s) );
ccf0a4a8 2033 if (cstring_compareLit (temp, "post:") == 0 )
920a3797 2034 {
3814599d 2035 postconditions = constraintList_undump (f);
920a3797 2036 }
28bf4b0b 2037 else
2038 {
ccf0a4a8 2039 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
28bf4b0b 2040 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2041 }
2042
ccf0a4a8 2043 cstring_free (temp);
920a3797 2044
3814599d 2045 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2046 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
920a3797 2047
2048 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2049 }
2050
616915dd 2051 dbgload = FALSE;
2052 sfree (os);
2053}
2054
2055/*
2056** file scope for static variables
2057*/
2058
2059void
2060usymtab_enterFile ()
2061 /*@globals utab, globtab, filetab@*/
2062 /*@modifies filetab@*/
2063{
2064 llassert (utab == globtab);
2065
2066 # if 0
2067 /* check globals */
2068
2069 usymtab_entries (globtab, ue)
2070 {
2071 if (sRef_hasDerived (uentry_getSref (ue)))
2072 {
2073 fprintf (g_msgstream, "Derived Global: %s\n", uentry_unparse (ue));
2074 fprintf (g_msgstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2075 }
2076 } end_usymtab_entries ;
2077
2078 # endif
2079
2080 usymtab_enterScope ();
2081 filetab = utab;
2082}
2083
2084void
2085usymtab_exitFile ()
2086 /*@globals utab, filetab@*/
2087 /*@modifies filetab, utab@*/
2088{
2089
2090 llassert (utab->lexlevel == 1);
2091
2092 usymtab_exitScope (exprNode_undefined);
2093 filetab = NULL;
2094}
2095
2096void
2097usymtab_enterScope ()
2098 /*@globals utab, globtab, filetab@*/
2099 /*@modifies utab@*/
2100{
2101 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2102
2103 /* unconditional scope: optimize to avoid copy */
2104 t->aliases = aliasTable_copy (utab->aliases);
2105 utab = t;
2106
2107 llassert (usymtab_isDefined (t->env));
2108
2109 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2110 {
2111 noshadowerror = TRUE;
2112 usymtab_handleParams ();
2113 noshadowerror = FALSE;
2114 }
2115}
2116
2117/*
2118** setup external references:
2119** o only, unique params alias external args
2120** o other params may alias anything of their type
2121*/
2122
2123static void
2124usymtab_handleParams (void)
2125 /*@globals utab, globtab, filetab@*/
2126 /*@modifies utab, globtab@*/
2127{
2128 usymtab ptab = utab->env;
2129 uentry fcn = context_getHeader ();
2130
616915dd 2131 usymtab_entries (ptab, param)
2132 {
2133 uentry ue;
2134
2135 if (!uentry_isYield (param))
2136 {
2137 sRef uref;
2138 sRef pref = uentry_getSref (param);
616915dd 2139
28bf4b0b 2140 /* Could be a global. */
616915dd 2141
28bf4b0b 2142 if (uentry_isAnyParam (param))
2143 {
2144 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2145 uentry_getType (param),
2146 fileloc_copy (uentry_whereDeclared (param)),
2147 FALSE);
2148
2149 uentry_copyState (ue, param);
2150 uentry_setRefParam (ue);
2151
2152 ue = usymtab_supEntrySrefReturn (ue);
2153
2154 /* must be after supercede! */
2155
2156 if (!sRef_stateKnown (pref))
616915dd 2157 {
28bf4b0b 2158 uentry_setDefState (ue, SS_DEFINED);
2159 uentry_setDefState (param, SS_DEFINED);
616915dd 2160 }
2161 else
2162 {
28bf4b0b 2163 if (sRef_isStateSpecial (pref))
2164 {
3e3ec469 2165 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2166 /* evans 2002-01-01: should be unnecessary, the pre clauses
2167 ** set the state if necessary.
2168 */
28bf4b0b 2169 }
2170 else
2171 {
2172 uentry_setDefState (ue, sRef_getDefState (pref));
2173 }
616915dd 2174 }
28bf4b0b 2175
2176 uref = uentry_getSref (ue);
2177
2178 if (sRef_isStack (uref))
616915dd 2179 {
28bf4b0b 2180 alkind pkind = sRef_getAliasKind (pref);
2181
2182 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2183 && !alkind_isStack (pkind))
616915dd 2184 {
28bf4b0b 2185 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2186 sRef_setOrigAliasKind (uref, pkind);
616915dd 2187 }
2188 else
2189 {
28bf4b0b 2190 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2191 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2192
2193 if (uentry_isOut (param))
2194 {
2195 ;
2196 }
2197 else
2198 {
2199 sRef_setDefined (uref, fileloc_undefined);
2200 }
616915dd 2201 }
28bf4b0b 2202
616915dd 2203 }
28bf4b0b 2204
2205 usymtab_addMustAlias (uref, pref);
2206
2207 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2208 {
2209 /*
2210 ** This is needed for detecting possibly aliased parameters.
2211 */
616915dd 2212
28bf4b0b 2213 sRef s = sRef_makeExternal (uref);
2214 usymtab_addMustAlias (uref, s);
2215 }
2216
2217 if (sRef_isKillRef (pref))
2218 {
2219 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2220 sRef_setOrigAliasKind (uref, AK_KILLREF);
2221 }
2222 else if (sRef_isRefCounted (uref))
2223 {
2224 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2225 }
2226 else
2227 {
2228 /* was AK_UNIQUE */
2229 sRef_setOrigAliasKind (uref, AK_LOCAL);
2230 }
616915dd 2231 }
2232 else
2233 {
616915dd 2234 }
2235 }
616915dd 2236 } end_usymtab_entries;
28bf4b0b 2237
2238
2239 if (uentry_hasStateClauseList (fcn))
616915dd 2240 {
28bf4b0b 2241 stateClauseList clauses = uentry_getStateClauseList (fcn);
2242
2243 stateClauseList_preElements (clauses, cl)
616915dd 2244 {
28bf4b0b 2245 fileloc loc = stateClause_loc (cl);
2246 sRefSet osrs = sRefSet_undefined;
2247 sRefSet srs;
616915dd 2248
28bf4b0b 2249 if (stateClause_isGlobal (cl))
2250 {
2251 DPRINTF (("Global Marker: %s",
2252 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2253 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2254 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2255 osrs = srs;
2256 }
2257 else
2258 {
2259 srs = stateClause_getRefs (cl);
2260 }
2261
2262 sRefSet_elements (srs, el)
616915dd 2263 {
2264 sRef base = sRef_getRootBase (el);
28bf4b0b 2265 sRef sb = sRef_updateSref (el);
2266
616915dd 2267 if (sRef_isResult (base))
2268 {
2269 ; /* nothing to do before */
2270 }
28bf4b0b 2271 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
616915dd 2272 {
28bf4b0b 2273 if (stateClause_setsMetaState (cl))
616915dd 2274 {
28bf4b0b 2275 /* copied from exprNode.c:3040 */
2276 qual ql = stateClause_getMetaQual (cl);
2277 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2278 metaStateInfo minfo = annotationInfo_getState (ainfo);
2279 cstring key = metaStateInfo_getName (minfo);
2280 int mvalue = annotationInfo_getValue (ainfo);
616915dd 2281
28bf4b0b 2282 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2283
2284 if (sRef_isResult (base))
616915dd 2285 {
28bf4b0b 2286 BADBRANCH;
2287 }
2288 else
2289 {
2290 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2291 }
2292 }
2293 else
2294 {
2295 sRefMod modf = stateClause_getEntryFunction (cl);
2296
2297 if (modf != NULL)
2298 {
2299 sRefSet aliases = usymtab_allAliases (sb);
2300
2301 modf (sb, loc);
2302
2303 sRefSet_elements (aliases, sr)
2304 {
2305 modf (sr, loc);
2306 } end_sRefSet_elements ;
2307
2308 sRefSet_free (aliases);
2309 }
616915dd 2310 }
2311 }
2312 else
2313 {
2314 if (sRef_isValid (base))
2315 {
28bf4b0b 2316 DPRINTF (("Base: %s", sRef_unparseFull (base)));
616915dd 2317 BADBRANCH;
2318 }
2319 }
2320 } end_sRefSet_elements ;
28bf4b0b 2321 } end_stateClauseList_preElements ;
2322 }
2323}
2324
616915dd 2325void
2326usymtab_enterFunctionScope (uentry fcn)
2327 /*@globals utab, filetab, globtab@*/
2328 /*@modifies utab@*/
2329{
2330 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2331
2332 if (utab->lexlevel != fileScope)
2333 {
2334 if (utab->lexlevel > fileScope)
2335 {
7ebcc5bb 2336 llparseerror (cstring_makeLiteral ("New function scope inside function"));
616915dd 2337
2338 while (utab->lexlevel > fileScope)
2339 {
2340 /*@i@*/ utab = usymtab_dropEnv (utab);
2341 /*@-branchstate@*/
2342 }
2343 /*@=branchstate@*/
2344 }
2345 else
2346 {
2347 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2348 }
2349 /*@-branchstate@*/ } /*@=branchstate@*/
2350
28bf4b0b 2351 utab = t;
2352
2353 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2354
616915dd 2355 globSet_allElements (uentry_getGlobs (fcn), el)
2356 {
28bf4b0b 2357 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
616915dd 2358
2359 if (sRef_isUndefGlob (el))
2360 {
2361 int index = sRef_getScopeIndex (el);
2362 sRef sr = sRef_updateSref (el);
2363 fileloc loc = uentry_whereEarliest (fcn);
28bf4b0b 2364
2365 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2366 DPRINTF (("Undef!"));
616915dd 2367 if (sRef_isFileStatic (el))
2368 {
2369 ctype ct = sRef_getType (el);
2370 uentry ue;
2371
2372 llassert (usymtab_isDefined (filetab));
2373
2374 ue = usymtab_fetchIndex (filetab, index);
2375
2376 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2377 {
2378 sRef_setAllocated (sr, loc);
2379 }
2380 else
2381 {
2382 sRef_setUndefined (sr, loc);
2383 }
2384 }
2385 else
2386 {
2387 uentry ue = globtab->entries[index];
2388 ctype ct = uentry_getType (ue);
2389
2390 if (ctype_isArray (ct) || ctype_isSU (ct))
2391 {
2392 sRef_setAllocated (sr, loc);
2393 }
2394 else
2395 {
2396 sRef_setUndefined (sr, loc);
2397 }
2398 }
2399 }
2400 else if (sRef_isAllocated (el))
2401 {
2402 sRef sr = sRef_updateSref (el);
2403 fileloc loc = uentry_whereEarliest (fcn);
2404
2405 sRef_setAllocated (sr, loc);
2406 }
2407 else if (sRef_isPartial (el))
2408 {
2409 sRef sr = sRef_updateSref (el);
2410 fileloc loc = uentry_whereEarliest (fcn);
2411
2412 sRef_setPartial (sr, loc);
2413 }
2414 else
2415 {
28bf4b0b 2416 /*
2417 sRef sr = sRef_updateSref (el);
2418 fileloc loc = uentry_whereEarliest (fcn);
2419
2420 sRef_setDefined (sr, loc);
2421 */
2422
2423 /* defined */
2424 /* shouldn't need to do anything! */
616915dd 2425 }
2426 } end_globSet_allElements;
2427
28bf4b0b 2428 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
616915dd 2429}
2430
2431static void
2432usymtab_caseBranch (void)
2433 /*@modifies utab@*/
2434{
2435 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2436 utab = t;
2437}
2438
2439void
2440usymtab_switchBranch (/*@unused@*/ exprNode s)
2441 /*@modifies utab@*/
2442{
2443 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2444
2445 t->aliases = aliasTable_copy (utab->aliases);
28bf4b0b 2446 utab = t;
616915dd 2447}
2448
2449void
2450usymtab_trueBranch (/*@only@*/ guardSet guards)
2451 /*@modifies utab@*/
2452{
2453 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2454
2455 /*
2456 ** not true! (could be in a macro)
2457 **
2458 ** llassertprint (utab->lexlevel > paramsScope,
2459 ** ("not in scope: %s", usymtab_unparseLocal ()));
2460 **
2461 */
2462
2463 guardSet_free (t->guards);
2464 t->guards = guards;
28bf4b0b 2465
2466 aliasTable_free (t->aliases);
616915dd 2467 t->aliases = aliasTable_copy (utab->aliases);
2468
28bf4b0b 2469 utab = t;
616915dd 2470}
2471
2472/*
2473** consider,
2474**
2475** { int a; if (...) a = 3; < a may be undefined here!
2476**
2477*/
2478
2479void
28bf4b0b 2480usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
616915dd 2481{
2482 /*
2483 ** add a false branch
2484 ** (could be done more efficiently as a special case, but
2485 ** it is better to only maintain one version of the code)
2486 */
2487
28bf4b0b 2488 if (utab->kind != US_TBRANCH
2489 && context_inIterDef ())
2490 {
2491 usymtab_exitScope (expr);
2492 }
2493 else
2494 {
2495 DPRINTF (("pop true branch.."));
2496 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2497 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2498 }
616915dd 2499}
2500
2501void
2502usymtab_popCaseBranch () /*@modifies utab@*/
2503{
2504 llassert (utab->kind == US_CBRANCH);
2505 usymtab_quietPlainExitScope ();
2506}
2507
2508void
2509usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2510{
2511 /*
2512 ** add a false branch that must return --- that is,
2513 ** the true branch is always executed!
2514 */
2515
2516 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2517 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2518}
2519
2520void
2521usymtab_popOrBranch (exprNode pred, exprNode expr)
2522 /*@modifies utab@*/
2523{
2524 bool mustReturn;
2525 usymtab env = utab->env;
2526 usymtab otab = utab;
2527 int i = 0;
2528
2529 llassert (env != NULL);
2530
2531 if (exprNode_isError (expr))
2532 {
2533 mustReturn = FALSE;
2534 }
2535 else
2536 {
2537 mustReturn = exprNode_mustEscape (expr);
2538 }
2539
2540
2541 llassert (utab->kind == US_TBRANCH);
2542
2543 /*
2544 ** merge each entry in table with its original
2545 ** unless execution cannot continue after this branch
2546 */
2547
2548 for (i = 0; i < utab->nentries; i++)
2549 {
2550 uentry current = utab->entries[i];
2551 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2552
2553 uentry_mergeState (old, current, exprNode_loc (expr),
2554 mustReturn, FALSE, TRUE, ORCLAUSE);
2555 }
2556
2557
2558 if (mustReturn)
2559 {
2560 env->guards = guardSet_levelUnionFree (env->guards,
2561 guardSet_invert (exprNode_getGuards (pred)),
2562 env->lexlevel);
2563 }
2564 else
2565 {
2566 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2567 }
2568
2569 /* env is now utab */
2570 usymtab_quietPlainExitScope ();
2571}
2572
2573/*
2574** case syntax in C is very unrestricted. This is unfortunate.
2575**
2576** A switch case is ended either by a new case or default, or
2577** a close } that may close the switch or some other control
2578** structure.
2579*/
2580
2581bool
2582usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2583 /*@modifies utab@*/
2584{
2585 bool mustBreak = usymtab_mustBreak (utab);
2586 bool mustReturn = usymtab_mustEscape (utab);
2587 usymtab stab = utab;
2588
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 }
2598
2599 /* ??? */
2600
2601 while (stab->kind == US_CBRANCH)
2602 {
2603 stab = stab->env;
2604 llassert (stab != GLOBAL_ENV);
2605 }
2606
2607 /*
2608 ** if its a fall through case, merge in outside entries and last case.
2609 **
2610 ** e.g.,
2611 ** ...
2612 ** switch
2613 ** case 1: x = 3; <fall through>
2614 ** case 2: << x may not be defined
2615 **
2616 */
2617
2618 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2619 {
2620 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2621
2622 usymtab_entries (utab, ue) /* but, keep track of used variables */
2623 {
2624 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2625
2626 llassert (uentry_isValid (old));
2627
2628 /* modifies ue, not old */
2629
2630 uentry_mergeState (ue, old, exprNode_loc (last),
2631 FALSE, FALSE, TRUE, CASECLAUSE);
2632 } end_usymtab_entries;
2633
2634 utab->aliases = aliasTable_levelUnion (utab->aliases,
2635 stab->aliases, utab->lexlevel);
2636
2637 /*
2638 ** No need for a new branch.
2639 */
2640
2641 return FALSE;
2642 }
2643 else
2644 {
2645 usymtab_caseBranch ();
2646 /*@-mustfree@*/ /*< utab->aliases >*/
2647 utab->aliases = aliasTable_copy (stab->aliases);
2648 /*@=mustfree@*/
2649
2650 return TRUE;
2651 }
2652}
2653
2654/*
2655** for && (both pred and expr are executed)
2656*/
2657
2658void
2659usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2660 /*@modifies utab@*/
2661{
2662 usymtab env = utab->env;
2663 usymtab otab= utab;
2664 int i = 0;
2665
28bf4b0b 2666 llassert (utab->kind == US_TBRANCH);
616915dd 2667
2668 /*
2669 ** merge each entry in table with its original
2670 ** unless execution cannot continue after this branch
2671 */
2672
2673 for (i = 0; i < utab->nentries; i++)
2674 {
2675 uentry current = utab->entries[i];
2676 sRef tref = uentry_getSref (current);
2677 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2678 sRef oref = uentry_getSref (old);
2679
2680 /* note that is current is in a nested branch,
2681 it may create a "new" old entry. */
2682
2683 llassert (uentry_isValid (old));
2684 uentry_mergeState (old, current, exprNode_loc (expr),
2685 FALSE, FALSE, TRUE, ANDCLAUSE);
2686
2687 /*
2688 ** if is it defined by the second clause, then it should be defined.
2689 */
2690
2691 if (sRef_isAnyDefined (tref)
2692 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2693 {
2694 sRef_setDefined (oref, g_currentloc);
2695 }
2696 }
2697
2698 utab->guards = guardSet_levelUnionFree (utab->guards,
2699 guardSet_invert (exprNode_getGuards (pred)),
2700 utab->lexlevel);
2701 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2702
2703 usymtab_quietPlainExitScope ();
2704
2705 }
2706
2707/*
2708** Stack should be [ US_CBRANCH+ US_SWITCH ]
2709** Only branches which do not return (except possibly the last branch) are included.
2710**
2711** Conditionally merge state from all CBRANCHes.
2712**
2713** If allpaths is TRUE, then all possible executions go through some switch
2714** case, and the original scope is not merged.
2715*/
2716
2717void
2718usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2719 /*@modifies utab@*/
2720{
2721 usymtab ttab = utab;
2722 usymtab stab = ttab;
2723 usymtab ltab = ttab;
2724 bool lastMustReturn = usymtab_mustEscape (utab);
2725 int i;
2726
2727
2728 while (stab->kind == US_CBRANCH)
2729 {
2730 stab = stab->env;
2731 llassert (stab != GLOBAL_ENV);
2732 }
2733
2734 while (stab->kind == US_NORMAL)
2735 {
2736 stab = stab->env;
2737 llassert (stab != GLOBAL_ENV);
2738 }
2739
2740 llassert (stab->kind == US_SWITCH);
2741
2742 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2743 stab = stab->env;
2744 llassert (stab != GLOBAL_ENV);
2745
2746
2747 ttab = ttab->env;
2748 llassert (usymtab_isDefined (ttab));
2749
2750 if (ttab->kind == US_CBRANCH)
2751 {
2752 /* was quietPlainExitScope --- but, can't free it yet! */
2753 utab = utab->env;
2754 llassert (utab != GLOBAL_ENV);
2755
2756 while (ttab->kind == US_CBRANCH)
2757 {
2758 /*
2759 ** (from popTrueBranch)
2760 */
2761
2762 bool mustReturn = usymtab_mustEscape (ttab);
2763 bool mustBreak = usymtab_mustBreak (ttab);
2764
2765 usymtab_entries (ttab, current)
2766 {
2767 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2768 /*@=compmempass@*/
2769
2770 /*
2771 ** note that is this is in a nested branch,
2772 ** it may create a "new" old entry.
2773 */
2774
2775 if (uentry_isValid (old))
2776 {
2777 if (lastMustReturn)
2778 {
2779 uentry_mergeUses (current, old);
2780 uentry_setState (old, current);
2781 }
2782 else
2783 {
2784 uentry_mergeState (old, current, exprNode_loc (sw),
2785 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2786 }
2787 }
2788 else
2789 {
2790 ;
2791 }
2792 } end_usymtab_entries;
2793
2794 /*
2795 ** if entry is not in symbol table for this case, merge with pre-switch
2796 ** table
2797 */
2798
2799 if (!mustReturn && !mustBreak)
2800 {
2801 usymtab_entries (stab, current)
2802 {
2803 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2804 {
2805 uentry old = /*@-compmempass@*/
2806 usymtab_lookupAux (ltab, uentry_rawName (current));
2807 /*@=compmempass@*/
2808
2809 llassert (uentry_isValid (old));
2810 uentry_mergeState (old, current, exprNode_loc (sw),
2811 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2812 }
2813 } end_usymtab_entries;
2814 }
2815
2816 ltab->env = ttab->env;
2817 ttab = ltab->env;
2818
2819 /*
2820 ** Suprious error, becuase of environments.
2821 */
2822
2823 /*@i1@*/ utab = ltab;
2824
2825 lastMustReturn = FALSE;
2826 /*@-branchstate@*/
2827 }
2828 }
2829 /*@=branchstate@*/
2830
2831 /*
2832 ** now, there is one US_CBRANCH. Merge this with the stab.
2833 */
2834
2835
2836 for (i = 0; i < ltab->nentries; i++)
2837 {
2838 uentry current = ltab->entries[i];
2839 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2840
2841 /* note that is this is in a nested branch,
2842 it may create a "new" old entry. */
2843
2844
2845 if (uentry_isValid (old))
2846 {
2847 if (allpaths)
2848 {
2849 uentry_mergeUses (current, old);
2850 uentry_setState (old, current);
2851 }
2852 else
2853 {
2854 uentry_mergeState (old, current, exprNode_loc (sw),
2855 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2856 }
2857 }
2858 else
2859 {
2860 }
2861 }
2862
2863 /*
2864 ** exit the switch
2865 */
2866
2867
2868 /*
2869 ** switch may or may not be followed by a new scope
2870 */
2871
2872 if (utab->kind == US_SWITCH)
2873 {
2874 usymtab_quietPlainExitScope ();
2875 }
2876 else
2877 {
2878 usymtab_quietPlainExitScope ();
2879 llassert (utab->kind == US_SWITCH);
2880 usymtab_quietPlainExitScope ();
2881 }
2882
2883 }
2884
2885static void
2886updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2887 /*@notnull@*/ usymtab ftab, bool trueGuard)
2888{
2889 sRef base = sRef_getRootBase (el);
28bf4b0b 2890 int level = sRef_lexLevel (base);
616915dd 2891
2892 if (sRef_isCvar (base))
2893 {
2894 usymId index = sRef_getScopeIndex (base);
2895 uentry ue = usymtab_getRefTab (ttab, level, index);
2896
2897 if (!uentry_isLset (ue))
2898 {
2899 sRef sr = uentry_getSref (ue);
2900
2901 if (trueGuard)
2902 {
2903 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2904 }
2905 else
2906 {
2907 if (!guardSet_isGuarded (ttab->guards, el)
2908 && !sRef_isNotNull (sr))
2909 {
2910 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2911 }
2912 }
2913 }
2914 else
2915 {
2916 }
2917
2918 ue = usymtab_getRefTab (ftab, level, index);
2919
2920 if (!uentry_isLset (ue))
2921 {
2922 sRef sr = uentry_getSref (ue);
2923
2924
2925 if (!trueGuard) /* yikes! forgot the ! */
2926 {
2927 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2928 }
2929 else
2930 {
2931
2932 if (!guardSet_isGuarded (ftab->guards, el)
2933 && !sRef_isNotNull (sr))
2934 {
2935 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2936 }
2937 }
2938 }
2939 else
2940 {
28bf4b0b 2941 ;
2942 }
2943 }
2944}
616915dd 2945
2946void
2947usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2948 bool isOpt, clause cl)
2949 /*@modifies utab@*/
2950{
2951 int i = 0;
2952 usymtab ftab = utab;
2953 usymtab ttab = utab->env;
2954
2955 fileloc loc;
2956 usymtab env;
2957 guardSet guards = exprNode_getGuards (pred);
2958 sRefSet tguards = guardSet_getTrueGuards (guards);
2959 sRefSet fguards = guardSet_getFalseGuards (guards);
2960 bool mustReturnT = exprNode_mustEscape (tbranch);
2961 bool mustReturnF = exprNode_mustEscape (fbranch);
28bf4b0b 2962
2963 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
2964 bool_unparse (mustReturnT),
2965 bool_unparse (mustReturnF)));
2966
616915dd 2967 if (exprNode_isDefined (fbranch))
2968 {
2969 loc = exprNode_loc (fbranch);
2970 }
2971 else
2972 {
2973 loc = exprNode_loc (tbranch);
2974 }
2975
2976 llassert (usymtab_isDefined (ttab));
2977
2978 env = ttab->env;
2979
2980 llassert (usymtab_isDefined (env));
2981 llassert (ftab->kind == US_FBRANCH);
2982 llassert (ttab->kind == US_TBRANCH);
2983
2984 /*
2985 ** For each element that is true guarded (i.e., if (x != NULL))
2986 ** make x = null in false branch,
2987 ** and x = notnull in true branch.
2988 ** unless x was set locally in that branch.
2989 ** For each element that is false guarded (x == NULL)
2990 ** make x = null in true, notnull in false.
2991 **
2992 ** For each element that is either guarded (pred(x))
2993 **
2994 */
2995
2996 sRefSet_allElements (tguards, el)
2997 {
2998 updateNullState (el, ttab, ftab, TRUE);
2999 } end_sRefSet_allElements;
3000
3001 sRefSet_allElements (fguards, el)
3002 {
3003 updateNullState (el, ttab, ftab, FALSE);
3004 } end_sRefSet_allElements;
3005
3006 /*
3007 **
3008 ** if an entry is in both true and false, merge the entries,
3009 ** then replace original with new state.
3010 **
3011 ** if an entry is in one table, merge it with the original.
3012 */
28bf4b0b 3013
3014 DPRINTF (("ftab: %d", ftab->nentries));
3015
616915dd 3016 for (i = 0; i < ftab->nentries; i++)
3017 {
3018 uentry fthis = ftab->entries[i];
3019 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3020 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3021
28bf4b0b 3022 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3023
616915dd 3024 if (uentry_isUndefined (old))
3025 {
3026 /* possible entry was added as an undefined id */
28bf4b0b 3027 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
616915dd 3028 continue;
3029 }
3030
3031 if (tindex != NOT_FOUND)
3032 {
3033 uentry tthis = ttab->entries[tindex];
28bf4b0b 3034
616915dd 3035 /* note that is this is in a nested branch,
3036 it may create a "new" old entry. */
3037
3038 if (!mustReturnF)
3039 {
3040 if (!mustReturnT)
3041 {
616915dd 3042 uentry_mergeState (fthis, tthis, loc,
3043 mustReturnT, FALSE, FALSE, cl);
3044 }
3045 else
3046 {
3047 uentry_mergeUses (fthis, tthis);
3048 }
3049
3050 uentry_setState (old, fthis);
3051
3052 /*@-mustfree@*/
3053 }
3054 /*@=mustfree@*/
3055 else
3056 {
3057 uentry_setState (old, tthis);
3058 uentry_mergeState (old, fthis, loc, mustReturnF,
3059 TRUE, FALSE, cl);
3060 }
3061
3062 ttab->entries[tindex] = uentry_undefined;
3063 uentry_free (tthis);
3064 }
3065 else
3066 {
3067 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3068 }
3069 }
3070
3071 for (i = 0; i < ttab->nentries; i++)
3072 {
3073 uentry current = ttab->entries[i];
3074
28bf4b0b 3075 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3076
616915dd 3077 if (!uentry_isUndefined (current))
3078 {
3079 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3080
28bf4b0b 3081 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3082
3083 if (uentry_isUndefined (old))
3084 {
3085 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3086 continue;
3087 }
3088
616915dd 3089 if (mustReturnF)
3090 {
3091 uentry_mergeUses (current, old);
3092 uentry_setState (old, current);
3093 }
3094 else
3095 {
3096 /*
28bf4b0b 3097 ** Assumes false branch is a fall-through if
616915dd 3098 ** fbranch is not defined. This is true, unless
3099 ** where was some greivous error in processing
3100 ** the else branch of an if-then, in which case
3101 ** this is probably the right thing to do anyway.
3102 */
3103
3104 uentry_mergeState (old, current, loc, mustReturnT,
3105 FALSE, isOpt, cl);
3106 }
28bf4b0b 3107
3108 DPRINTF (("==> %s", uentry_unparseFull (old)));
616915dd 3109 }
3110 }
616915dd 3111
3112 /*
3113 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3114 ** if they are present.
3115 */
3116
3117 llassert (NOALIAS (env->aliases, ttab->aliases));
3118 llassert (NOALIAS (env->aliases, ftab->aliases));
3119
3120 aliasTable_free (env->aliases);
3121
3122 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3123 ftab->aliases, env->lexlevel);
3124
3125 aliasTable_fixSrefs (env->aliases);
28bf4b0b 3126
3127 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
616915dd 3128
3129 /* exit true and false scopes */
3130 usymtab_quietPlainExitScope ();
3131 usymtab_quietPlainExitScope ();
3132
3133 if (mustReturnT)
3134 {
3135 utab->guards = guardSet_levelUnionFree
3136 (utab->guards,
3137 guardSet_invert (exprNode_getGuards (pred)),
3138 utab->lexlevel);
3139 }
3140
3141 if (mustReturnF)
3142 {
3143 utab->guards = guardSet_levelUnion (utab->guards,
3144 exprNode_getGuards (pred),
3145 utab->lexlevel);
3146 }
3147
3148 DPRINTF (("Here."));
3149}
3150
3151static void usymtab_fixCases (void) /*@modifies utab@*/ {
3152 while (utab->kind == US_CBRANCH)
3153 {
3154 usymtab_quietPlainExitScope ();
3155 }
3156
3157 llassert (utab->kind != US_CBRANCH);
3158}
3159
3160void
3161usymtab_altBranch (/*@only@*/ guardSet guards)
3162 /*@modifies utab@*/
3163{
28bf4b0b 3164 usymtab t;
616915dd 3165 usymtab parent = utab->env;
3166
28bf4b0b 3167 t = usymtab_create (US_FBRANCH, utab, FALSE);
3168
616915dd 3169 /*
3170 ** If we are in a case, need to close it. The C syntax
3171 ** is very liberal, so this kludge is necessary.
3172 */
3173
3174 usymtab_fixCases ();
3175
3176 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
28bf4b0b 3177
616915dd 3178 llassert (utab->kind == US_TBRANCH);
3179 llassert (parent != GLOBAL_ENV);
28bf4b0b 3180
616915dd 3181 guardSet_free (t->guards);
3182 t->guards = guards;
28bf4b0b 3183
616915dd 3184 aliasTable_free (t->aliases);
3185 t->aliases = aliasTable_copy (parent->aliases);
28bf4b0b 3186
616915dd 3187 utab = t;
3188}
3189
3190void
3191usymtab_allDefined (void)
3192 /*@globals utab, globtab@*/
3193{
3194 int i;
3195
3196 llassert (utab == globtab);
3197
3198 for (i = 0; i < utab->nentries; i++)
3199 {
3200 uentry e = utab->entries[i];
3201
3202 if (uentry_isPriv (e))
3203 {
3204 ; /* no need to define it */
3205 }
3206 else
3207 {
3208 if (context_getFlag (FLG_SPECUNDECL))
3209 {
3210 fileloc sloc = uentry_whereSpecified (e);
3211 fileloc dloc = uentry_whereDeclared (e);
3212
3213 if (fileloc_isDefined (sloc)
3214 && !uentry_isFakeTag (e)
3215 && !fileloc_isDefined (dloc))
3216 {
3217 voptgenerror
3218 (FLG_SPECUNDECL,
3219 message ("%s %q specified but not declared",
3220 ekind_capName (uentry_getKind (e)),
3221 uentry_getName (e)),
3222 sloc);
3223 }
3224 }
3225
3226 if (!uentry_isCodeDefined (e))
3227 {
3228 fileloc dloc = uentry_whereDeclared (e);
3229
28bf4b0b 3230 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
616915dd 3231 {
3232 ;
3233 }
3234 else if (fileloc_isDefined (dloc))
3235 {
3236 if (!uentry_isAnyTag (e))
3237 {
3238 if (fileloc_isUser (dloc))
3239 {
3240 voptgenerror
3241 (FLG_DECLUNDEF,
3242 message ("%s %q declared but not defined",
3243 ekind_capName (uentry_getKind (e)),
3244 uentry_getName (e)),
3245 dloc);
efd360a3 3246 DPRINTF (("decl: %s", uentry_unparseFull (e)));
616915dd 3247 }
3248 }
3249 }
3250 else
3251 {
3252 fileloc sloc = uentry_whereSpecified (e);
3253
3254 if (fileloc_isDefined (sloc)
3255 && !fileloc_isImport (sloc)
3256 && !fileloc_isLib (sloc)
3257 && !fileloc_isPreproc (sloc)
3258 && !uentry_isFakeTag (e))
3259 {
3260 if (uentry_isVariable (e) || uentry_isFunction (e))
3261 {
3262 voptgenerror
3263 (FLG_SPECUNDEF,
3264 message ("%s %q specified but not declared or defined",
3265 ekind_capName (uentry_getKind (e)),
3266 uentry_getName (e)),
3267 sloc);
3268 }
3269 else
3270 {
3271 voptgenerror
3272 (FLG_SPECUNDEF,
3273 message ("%s %q specified but not defined",
3274 ekind_capName (uentry_getKind (e)),
3275 uentry_getName (e)),
3276 sloc);
3277 }
3278 }
3279 }
3280 }
3281 }
3282 }
3283}
3284
3285void usymtab_exportHeader (void)
3286 /*@globals utab@*/
3287{
3288 int i;
3289
3290 for (i = 0; i < utab->nentries; i++)
3291 {
3292 uentry ce = utab->entries[i];
3293
3294 if (!uentry_isDatatype (ce)
3295 && !uentry_isAnyTag (ce)
3296 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3297 && !uentry_isExternal (ce)
3298 && !uentry_isForward (ce))
3299 {
3300 fileloc fwhere = uentry_whereDeclared (ce);
3301
3302 if (fileloc_isUndefined (fwhere)
3303 && uentry_isFunction (ce))
3304 {
3305 fwhere = uentry_whereDefined (ce);
3306 }
3307
3308 if (fileloc_isDefined (fwhere)
3309 && !fileloc_isHeader (fwhere)
28bf4b0b 3310 && !fileloc_isXHFile (fwhere)
616915dd 3311 && !(fileloc_isSpecialFile (fwhere)
3312 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3313 {
3314 if (uentry_isVariable (ce))
3315 {
3316 if (optgenerror
3317 (FLG_EXPORTHEADERVAR,
3318 message ("%s %q exported but not declared in header file",
3319 ekind_capName (uentry_getKind (ce)),
3320 uentry_getName (ce)),
3321 fwhere))
3322 {
3323 uentry_showDefSpecInfo (ce, fwhere);
3324 }
3325 }
3326 else
3327 {
3328 if (!uentry_isIter (ce)
3329 && !uentry_isEndIter (ce)
3330 && !uentry_isExpandedMacro (ce))
3331 {
3332 if (uentry_isFunction (ce)
3333 && cstring_equalLit (uentry_rawName (ce), "main"))
3334 {
3335 ; /* no error for main */
3336 }
3337 else
3338 {
3339 if (optgenerror
3340 (FLG_EXPORTHEADER,
3341 message ("%s %q exported but not declared "
3342 "in header file",
3343 ekind_capName (uentry_getKind (ce)),
3344 uentry_getName (ce)),
3345 fwhere))
3346 {
3347 uentry_showDefSpecInfo (ce, fwhere);
3348 }
3349 }
3350 }
3351 }
3352 }
3353 }
3354 }
3355}
3356
3357void usymtab_exportLocal (void)
3358 /*@globals utab@*/
3359{
3360 int i;
616915dd 3361
3362 for (i = 0; i < utab->nentries; i++)
3363 {
3364 uentry ce = utab->entries[i];
616915dd 3365
3366 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3367 && !uentry_isEitherConstant (ce)
3368 && !uentry_isIter (ce)
3369 && !uentry_isEndIter (ce)
3370 && !uentry_isExpandedMacro (ce)
3371 && uentry_isUsed (ce))
3372 {
3373 /* check static uses */
3374 filelocList fuses = uentry_getUses (ce);
3375 fileloc mod = uentry_whereDefined (ce);
3376 bool ok = filelocList_isEmpty (fuses);
3377 fileloc fwhere = uentry_whereDeclared (ce);
3378
3379 if (fileloc_isSpecialFile (fwhere)
3380 && !context_getFlag (FLG_UNUSEDSPECIAL))
3381 {
3382 ok = TRUE; /* no errors for special files */
3383 }
3384 else
3385 {
3386 filelocList_elements (fuses, uloc)
3387 {
3388 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3389 {
3390 ok = TRUE;
3391 /*@innerbreak@*/ break;
3392 }
3393 } end_filelocList_elements;
3394 }
3395
3396 if (!ok)
3397 {
3398 if (optgenerror
3399 (FLG_EXPORTLOCAL,
3400 message ("%s exported but not used outside %s: %q",
3401 ekind_capName (uentry_getKind (ce)),
3402 fileloc_getBase (mod),
3403 uentry_getName (ce)),
3404 fwhere))
3405 {
3406 uentry_showDefSpecInfo (ce, fwhere);
3407 }
3408 }
3409 }
3410 }
3411}
3412
3413void
3414usymtab_allUsed (void)
3415 /*@globals utab@*/
3416{
3417 int i;
3418 bool isFileStatic = usymtab_inFileScope ();
3419 cstring last_file = cstring_undefined;
3420
3421 for (i = 0; i < utab->nentries; i++)
3422 {
3423 bool hasError = FALSE;
3424 uentry ce = utab->entries[i];
3425 fileloc fwhere = uentry_whereDeclared (ce);
3426
3427 if (fileloc_isUndefined (fwhere))
3428 {
3429 fwhere = uentry_whereDefined (ce);
3430 }
3431
3432 if (fileloc_isInvalid (fwhere)
3433 || fileloc_isLib (fwhere)
3434 || fileloc_isBuiltin (fwhere)
3435 || ((fileloc_isSpecialFile (fwhere)
3436 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3437 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3438 {
3439 ;
3440 }
3441 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3442 {
3443 cstring fname = fileloc_filename (fwhere);
3444
3445 if (cstring_isUndefined (last_file))
3446 {
3447 last_file = fname;
3448 }
3449 else if (cstring_equal (fname, last_file))
3450 {
3451 }
3452 else
3453 {
3454 cleanupMessages ();
3455 last_file = fname;
3456 }
3457
3458 if (uentry_isParam (ce))
3459 {
3460 if (context_inMacro ())
3461 {
3462 sRef cref = uentry_getSref (ce);
3463
3464 if (uentry_isYield (ce))
3465 {
3466 ; /* no checks (for now) */
3467 }
3468 else if (sRef_isSafe (cref))
3469 {
3470 ; /* no error */
3471 }
3472 else
3473 {
3474 if (uentry_hasRealName (ce))
3475 {
3476 hasError =
3477 optgenerror (FLG_MACROPARAMS,
3478 message ("Macro parameter %q not used",
3479 uentry_getName (ce)),
3480 fwhere);
3481 }
3482 }
3483 }
3484 else
3485 {
3486 if (cstring_equalFree (uentry_getName (ce),
3487 cstring_makeLiteral ("...")))
3488 {
3489 ;
3490 }
3491 else
3492 {
3493 hasError = optgenerror (FLG_PARAMUNUSED,
3494 message ("Parameter %q not used",
3495 uentry_getName (ce)),
3496 fwhere);
3497 }
3498 }
3499 } /* isParam */
3500 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3501 {
3502 if (fileloc_isUser (fwhere))
3503 {
3504 hasError = optgenerror
3505 (FLG_FUNCUNUSED,
3506 message ("%q %q declared but not used",
3507 cstring_makeLiteral
3508 (uentry_isIter (ce) ? "Iterator"
3509 : (isFileStatic ? "File static function" : "Function")),
3510 uentry_getName (ce)),
3511 fwhere);
3512 }
3513 }
3514 else if (uentry_isEndIter (ce))
3515 {
3516 ; /* no error (already reported for iter */
3517 }
3518 else if (uentry_isEnumConstant (ce))
3519 {
3520 if (fileloc_isUser (fwhere))
3521 {
3522 hasError = optgenerror
3523 (FLG_ENUMMEMUNUSED,
3524 message ("Enum member %q not used",
3525 uentry_getName (ce)),
3526 fwhere);
3527 }
3528 }
3529 else if (uentry_isConstant (ce))
3530 {
3531 if (fileloc_isUser (fwhere))
3532 {
3533 hasError = optgenerror
3534 (FLG_CONSTUNUSED,
3535 message ("Constant %q declared but not used",
3536 uentry_getName (ce)),
3537 fwhere);
3538 }
3539 }
3540 else if (uentry_isDatatype (ce))
3541 {
3542 if (fileloc_isUser (fwhere))
3543 {
3544 hasError = optgenerror
3545 (FLG_TYPEUNUSED,
3546 message ("Type %q declared but not used",
3547 uentry_getName (ce)),
3548 fwhere);
3549 }
3550 }
3551 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3552 { /* errors for ref params will be reported in the next scope */
3553 llassertprint (uentry_isVar (ce),
3554 ("ce: %s", uentry_unparseFull (ce)));
3555
3556 if (ctype_isFunction (uentry_getType (ce)))
3557 {
3558 if (fileloc_isUser (fwhere))
3559 {
3560 hasError = optgenerror
3561 (FLG_FUNCUNUSED,
3562 message ("%q %q declared but not used",
3563 cstring_makeLiteral
3564 (isFileStatic ? "File static function"
3565 : "Function"),
3566 uentry_getName (ce)),
3567 fwhere);
3568 }
3569 }
3570 else
3571 {
3572 if (fileloc_isUser (fwhere))
3573 {
3574
3575
3576 hasError = optgenerror
3577 (FLG_VARUNUSED,
3578 message ("%q %q declared but not used",
3579 cstring_makeLiteral
3580 (isFileStatic ? "File static variable"
3581 : "Variable"),
3582 uentry_getName (ce)),
3583 fwhere);
3584 }
3585 }
3586 }
3587 else
3588 {
3589 ; /* no errors */
3590 }
3591 } /* unused */
28bf4b0b 3592 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
616915dd 3593 { /* check all fields */
3594 ctype ct = uentry_getRealType (ce);
3595
3596
3597 while (ctype_isAP (ct))
3598 {
3599 ct = ctype_getBaseType (ct);
3600 }
3601
616915dd 3602 if (ctype_isSU (ct))
3603 {
3604 uentryList fields = ctype_getFields (ct);
3605
3606 uentryList_elements (fields, field)
3607 {
3608 if (!uentry_isUsed (field))
3609 {
3610 if (uentry_hasName (ce))
3611 {
3612 hasError |= optgenerror
3613 (FLG_FIELDUNUSED,
3614 message ("Field %q of %s %q declared but not used",
3615 uentry_getName (field),
3616 cstring_makeLiteralTemp
3617 (ctype_isStruct (ct) ? "structure" : "union"),
3618 uentry_getName (ce)),
3619 uentry_whereEarliest (field));
3620 }
3621 else
3622 {
28bf4b0b 3623 /*
3624 ** evans 2001-06-08
3625 ** Can't report these errors for unnamed structs.
3626 ** No way to tell when there are multiple consistent
3627 ** unnamed structure types. (Could go through table
3628 ** and mark them all unused...)
3629
616915dd 3630 hasError |= optgenerror
3631 (FLG_FIELDUNUSED,
3632 message ("Field %q of unnamed %s declared but not used",
3633 uentry_getName (field),
3634 cstring_makeLiteralTemp
3635 (ctype_isStruct (ct) ? "structure" : "union")),
3636 uentry_whereEarliest (field));
28bf4b0b 3637
3638 */
616915dd 3639 }
3640
3641 uentry_setUsed (field, fileloc_undefined);
3642 }
3643 } end_uentryList_elements;
3644 }
3645 }
3646 else
3647 {
3648 ; /* no errors */
3649 }
3650
3651 if (hasError)
3652 {
3653 if (uentry_isParam (ce) && context_inMacro ())
3654 {
3655 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3656 {
3657 uentry_showWhereSpecified (ce);
3658 }
3659 }
3660 else
3661 {
3662 uentry_showDefSpecInfo (ce, fwhere);
3663 }
3664
3665 uentry_setUsed (ce, fileloc_undefined);
3666 }
3667 }
3668}
3669
3670static void
3671checkGlobalReturn (uentry glob, sRef orig)
3672{
3673 sRef sr = uentry_getSref (glob);
3674
b7b694d6 3675 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
28bf4b0b 3676 uentry_unparseFull (glob),
3677 sRef_unparseFull (orig),
3678 sRef_unparseFull (sr)));
3679
3680 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3681
616915dd 3682 if (context_getFlag (FLG_GLOBSTATE))
3683 {
28bf4b0b 3684 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3685
616915dd 3686 if (sRef_isKilledGlob (orig))
3687 {
3688 if (sRef_isStateUndefined (sr)
3689 || sRef_isUnuseable (sr)
3690 || sRef_isStateUnknown (sr)
3691 || sRef_isDead (sr))
3692 {
3693 ;
3694 }
3695 else
3696 {
3697 ctype ct = ctype_realType (uentry_getType (glob));
3698
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 ();
616915dd 3715 (void) checkGlobalDestroyed (sr, g_currentloc);
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 {
3774 checkGlobReturn (glob);
3775 }
3776 }
3777 }
3778 }
3779}
3780
3781/*
3782** remember: check alias globals
3783*/
3784
3785void usymtab_checkFinalScope (bool isReturn)
3786 /*@globals utab@*/
3787{
3788 bool mustFree = context_getFlag (FLG_MUSTFREE);
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 {
3928 checkLocalDestroyed (sr, g_currentloc);
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 {
3957 if (canLoseReference (sr, g_currentloc))
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
3971 (FLG_MUSTFREE,
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
3989 (FLG_MUSTFREE,
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 {
28bf4b0b 4007 checkStructDestroyed (sr, g_currentloc);
616915dd 4008 }
4009 else
4010 {
28bf4b0b 4011 DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
4012
616915dd 4013 if (optgenerror
4014 (FLG_MUSTFREE,
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
4039 DPRINTF (("entry: %s", uentry_unparseFull (ce)));
4040
4041 if (mustDefine && uentry_isOut (ce)
4042 && !uentry_isOnly (ce))
4043 {
4044 if (!sRef_isReallyDefined (sr))
616915dd 4045 {
3e3ec469 4046 voptgenerror
4047 (FLG_MUSTDEFINE,
4048 message ("Out storage %q not defined before %q",
4049 uentry_getName (ce),
4050 cstring_makeLiteral
4051 (isReturn ? "return" : "scope exit")),
4052 g_currentloc);
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)));
4073 checkLoseRef (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)));
616915dd 4263 checkParamReturn (param);
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 {
28bf4b0b 4515 int index;
4516
4517 /*@access sRef@*/
4518 llassert (sr->info != NULL);
4519 llassert (sr->info->cvar != NULL);
4520 index = sr->info->cvar->index;
4521 /*@noaccess sRef@*/
616915dd 4522
4523 if (index < uentryList_size (context_getParams ()))
4524 {
4525 return index;
4526 }
4527 }
4528 }
4529 return -1;
4530}
4531
4532/*@dependent@*/ /*@exposed@*/ uentry
4533 usymtab_getParam (int paramno)
4534 /*@globals utab@*/
4535{
4536 /*
4537 ** requires in a function context (checked)
4538 **
4539 ** depends on no nested functions --- the function
4540 ** parameters are ALWAYS one scope inside the global scope
4541 ** and entered in order!
4542 */
4543 usymtab s = utab;
4544
4545 if (!context_inFunctionLike ())
4546 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4547 context_unparse ()));
4548
4549 while (s->lexlevel > paramsScope)
4550 {
4551 s = s->env;
4552 }
4553
4554 llassert (usymtab_isDefined (s));
4555
4556 if (paramno >= s->nentries)
4557 {
4558 /*
4559 ** Parse errors lead to this.
4560 */
4561
4562 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4563 ctype_unknown);
4564
4565 uentry_markOwned (err);
4566 return (err);
4567 }
4568
4569 return (s->entries[paramno]);
4570}
4571
4572static /*@dependent@*/ /*@exposed@*/ uentry
4573usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4574{
4575 uentry ue;
4576
616915dd 4577 ue = usymtab_getRefNoisy (u, level, index);
4578
616915dd 4579 if (uentry_isUndefined (ue))
4580 {
4581 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4582 index, level));
4583 }
616915dd 4584
4585 return ue;
4586}
4587
4588static /*@dependent@*/ /*@exposed@*/ usymtab
4589 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4590{
4591 if (s->kind == US_CBRANCH)
4592 {
4593 usymtab t = s;
4594
4595 do
4596 {
4597 t = s;
4598 s = s->env;
4599 llassert (s != GLOBAL_ENV);
4600 } while (s->kind == US_CBRANCH);
4601 /* drop all cases (except in nested scopes */
4602
4603 s = t;
4604 llassert (s != GLOBAL_ENV);
4605 }
4606
4607 if (s->kind == US_FBRANCH)
4608 {
4609 s = s->env; /* skip the true branch */
4610 llassert (usymtab_isDefined (s));
4611 llassert (s->kind == US_TBRANCH);
4612 }
4613
4614 llassert (s != GLOBAL_ENV);
4615 s = s->env;
4616
4617 return s;
4618}
4619
4620/*@dependent@*/ /*@exposed@*/ uentry
4621 usymtab_getRefQuiet (int level, usymId index)
4622 /*@globals utab@*/
4623{
4624 usymtab s = utab;
4625
4626
4627 llassert (s != NULL);
4628 llassert (index >= 0);
4629
4630 if (level > s->lexlevel)
28bf4b0b 4631 {
616915dd 4632 return uentry_undefined;
4633 }
4634
4635 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4636 level, s->lexlevel));
4637
4638 while (s->lexlevel > level)
4639 {
4640 if (usymtab_isBranch (s))
4641 {
4642 int eindex = refTable_lookup (s, level, index);
4643
4644 if (eindex != NOT_FOUND)
4645 {
4646 return (s->entries[eindex]);
4647 }
4648 }
4649
4650 s = usymtab_dropEnv (s);
4651 }
4652
4653 while (usymtab_isBranch (s) && s->lexlevel == level)
4654 {
4655 int eindex = refTable_lookup (s, level, index);
4656
4657 if (eindex != NOT_FOUND)
4658 {
4659 return (s->entries[eindex]);
4660 }
4661
4662 s = usymtab_dropEnv (s);
4663 }
4664
4665 if (index >= s->nentries)
4666 {
4667 return uentry_undefined;
4668 }
4669
4670 llassert (!uentry_isUndefined (s->entries[index]));
4671
4672 return s->entries[index];
4673}
4674
4675static /*@dependent@*/ /*@exposed@*/ uentry
4676usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4677{
4678 usymtab otab = s;
4679 uentry ue = uentry_undefined;
616915dd 4680
4681 llassert (index >= 0);
616915dd 4682
4683 while (s->lexlevel > level)
4684 {
616915dd 4685 if (usymtab_isBranch (s))
4686 {
4687 int eindex = refTable_lookup (s, level, index);
4688
4689 if (eindex != NOT_FOUND)
4690 {
4691 ue = s->entries[eindex];
4692
4693 if (s != otab)
4694 {
4695 while (!usymtab_isBranch (otab))
4696 {
4697 otab = usymtab_dropEnv (otab);
4698 llassert (otab != GLOBAL_ENV);
4699 }
4700
4701 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4702 {
4703 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4704 }
4705 else
4706 {
4707 ;
4708 }
4709 }
4710
4711 return ue;
4712 }
4713 }
4714
4715 s = usymtab_dropEnv (s);
4716 }
4717
4718 llassert (usymtab_isDefined (s));
4719
4720 while (usymtab_isBranch (s) && s->lexlevel == level)
4721 {
4722 int eindex = refTable_lookup (s, level, index);
4723
4724
4725 if (eindex != NOT_FOUND)
4726 {
4727 ue = s->entries[eindex];
4728
4729 if (s != otab)
4730 {
4731 while (!usymtab_isBranch (otab))
4732 {
4733 otab = usymtab_dropEnv (otab);
4734 llassert (otab != GLOBAL_ENV);
4735 }
4736
4737 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4738 }
4739 else
4740 {
4741 ;
4742 }
4743
4744 return ue;
4745 }
4746
4747 s = usymtab_dropEnv (s);
4748 }
4749
4750 if (s->lexlevel == level && (index < s->nentries))
4751 {
4752 ue = s->entries[index];
4753
4754 if (uentry_isValid (ue))
4755 {
4756 if (s != otab)
4757 {
4758 while (!usymtab_isBranch (otab))
4759 {
4760 otab = usymtab_dropEnv (otab);
4761
4762 if (otab == GLOBAL_ENV)
4763 {
4764 return ue;
4765 }
4766 }
4767
4768 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4769 }
4770 else
4771 {
28bf4b0b 4772 }
616915dd 4773 }
28bf4b0b 4774
616915dd 4775 return ue;
4776 }
4777
4778
4779 if (index >= s->nentries)
4780 {
4781 return uentry_undefined;
4782 }
4783
4784 llassert (!uentry_isUndefined (s->entries[index]));
4785
4786 return s->entries[index];
4787}
4788
4789/*
4790** looking up entries
4791**
4792** If entry is inside a branch, then copy it, and put it into
4793** the branch table.
4794*/
4795
4796static
4797int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4798{
4799 refTable rt = ut->reftable;
4800 int i;
4801
4802 llassert (rt != NULL);
4803
616915dd 4804 for (i = 0; i < ut->nentries; i++)
4805 {
4806 if (rt[i]->level == level && rt[i]->index == index)
4807 {
28bf4b0b 4808 return i;
616915dd 4809 }
4810 }
28bf4b0b 4811
4812 return NOT_FOUND;
616915dd 4813}
4814
4815static
4816/*@only@*/ refentry refentry_create (int level, int index)
4817{
4818 refentry r = (refentry) dmalloc (sizeof (*r));
4819
4820 r->level = level;
4821 r->index = index;
4822
4823 return r;
4824}
4825
4826static /*@dependent@*/ /*@exposed@*/ uentry
4827usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4828{
4829 int eindex;
4830 usymtab ut = s;
4831
28bf4b0b 4832 if (ut->reftable == NULL)
4833 {
4834 DPRINTF (("Adding ref entry without reftable: %s", k));
4835 return uentry_undefined;
4836 }
616915dd 4837
28bf4b0b 4838 llassert (ut->reftable != NULL);
4839
616915dd 4840 while (s != GLOBAL_ENV)
4841 {
4842 eindex = usymtab_getIndex (s, k);
4843
4844 if (eindex != NOT_FOUND)
4845 {
4846 uentry current = s->entries[eindex];
4847
4848 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4849 {
4850 uentry ue;
4851
28bf4b0b 4852 DPRINTF (("Here: copying %s", uentry_unparse (current)));
616915dd 4853 ue = uentry_copy (current);
28bf4b0b 4854 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
616915dd 4855 usymtab_addEntryQuiet (ut, ue);
28bf4b0b 4856 DPRINTF (("Okay..."));
4857
616915dd 4858 if (s->reftable != NULL)
4859 {
4860 refentry ref = s->reftable[eindex];
616915dd 4861
4862 ut->reftable[ut->nentries - 1]
4863 = refentry_create (ref->level, ref->index);
4864 }
4865 else
4866 {
4867 ut->reftable[ut->nentries - 1]
4868 = refentry_create (s->lexlevel, eindex);
4869 }
4870
4871 return (ue);
4872 }
4873 else
4874 {
4875 return (current);
4876 }
4877 }
4878
4879 s = usymtab_dropEnv (s);
4880 }
4881
4882 return uentry_undefined;
4883}
4884
4885static uentry usymtab_lookupAux (usymtab s, cstring k)
4886{
4887 DPRINTF (("Lookup: %s", k));
4888
4889 while (s != GLOBAL_ENV)
4890 {
4891 int eindex = usymtab_getIndex (s, k);
4892
4893 if (eindex != NOT_FOUND)
4894 {
4895 uentry ret = s->entries[eindex];
28bf4b0b 4896# if 0
4897
616915dd 4898
28bf4b0b 4899 if (s->kind == US_TBRANCH
4900 || s->kind == US_FBRANCH
4901 || s->kind == US_CBRANCH)
4902 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4903 {
4904 uentry ret;
4905 DPRINTF (("Adding global ref entry: %s", k));
4906 ret = usymtab_addRefEntry (os, k);
4907 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4908 return ret;
4909 }
4910
4911# endif
616915dd 4912 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4913 return (ret);
4914 }
28bf4b0b 4915
616915dd 4916 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4917 || s->kind == US_CBRANCH)
4918 {
28bf4b0b 4919 /* why isn't this os??? */
616915dd 4920 uentry ret = usymtab_addRefEntry (s, k);
28bf4b0b 4921 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
616915dd 4922 return ret;
4923 }
4924
4925 s = s->env;
4926 }
4927
4928 return uentry_undefined;
4929}
4930
4931static /*@dependent@*/ /*@exposed@*/ uentry
28bf4b0b 4932usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
616915dd 4933{
4934 int eindex;
4935
4936 while (s != GLOBAL_ENV)
4937 {
4938 eindex = usymtab_getIndex (s, k);
4939
4940 if (eindex != NOT_FOUND)
4941 {
4942 uentry ret = s->entries[eindex];
4943 return (ret);
4944 }
4945
28bf4b0b 4946 if (noalt && usymtab_isBranch (s))
4947 {
4948 s = usymtab_dropEnv (s);
4949 }
4950 else
4951 {
4952 s = s->env;
4953 }
616915dd 4954 }
4955
4956 return uentry_undefined;
4957}
4958
28bf4b0b 4959static /*@exposed@*/ /*@dependent@*/ uentry
4960usymtab_lookupQuiet (usymtab s, cstring k)
4961{
4962 return usymtab_lookupQuietAux (s, k, FALSE);
4963}
4964
4965static /*@exposed@*/ /*@dependent@*/ uentry
4966usymtab_lookupQuietNoAlt (usymtab s, cstring k)
4967{
4968 return usymtab_lookupQuietAux (s, k, TRUE);
4969}
4970
616915dd 4971/*@dependent@*/ /*@observer@*/ uentry
4972 usymtab_lookupSafe (cstring k)
4973 /*@globals utab@*/
4974{
4975 DPRINTF (("Lookup safe: %s", k));
4976 return (usymtab_lookupAux (utab, k));
4977}
4978
4979uentry
4980 usymtab_lookupExpose (cstring k)
4981 /*@globals utab@*/
4982{
4983 uentry ce = usymtab_lookupAux (utab, k);
4984
4985 if (uentry_isUndefined (ce))
4986 {
4987 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
4988 }
4989
4990 if (uentry_isPriv (ce))
4991 {
4992 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
4993 }
4994
4995 return ce;
4996}
4997
4998uentry usymtab_lookupExposeGlob (cstring k)
4999{
5000 return (usymtab_lookupGlobSafe (k));
5001}
5002
5003uentry usymtab_lookupGlob (cstring k)
5004 /*@globals globtab@*/
5005{
5006 uentry ce = usymtab_lookupAux (globtab, k);
5007
5008 if (uentry_isUndefined (ce))
5009 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5010
5011 if (uentry_isPriv (ce))
5012 llfatalbug (message ("usymtab_lookup: private: %s", k));
5013
5014 return ce;
5015}
5016
5017/*@observer@*/ uentry
5018 usymtab_lookupGlobSafe (cstring k)
5019 /*@globals globtab@*/
5020{
5021 uentry ce = usymtab_lookupAux (globtab, k);
5022
5023 return ce;
5024}
5025
5026uentry usymtab_lookupEither (cstring k)
5027 /*@globals utab@*/
5028{
5029 uentry ce = usymtab_lookupSafe (k);
5030
5031 if (uentry_isUndefined (ce))
5032 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5033
5034 return ce;
5035}
5036
5037# ifndef NOLCL
5038ctype
5039usymtab_lookupType (cstring k)
5040 /*@globals globtab@*/
5041{
5042 usymId uid = usymtab_getTypeId (k);
5043
5044 if (uid == USYMIDINVALID)
5045 {
5046 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5047 return ctype_unknown;
5048 }
5049
5050 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5051}
5052# endif
5053
5054ctype
5055usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5056{
5057 usymId uid = usymtab_getTypeId (k);
5058
5059 if (uid == USYMIDINVALID)
5060 {
5061 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5062 return ctype_unknown;
5063 }
5064
5065 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5066}
5067
5068/*
5069** if there is an unnamed lcl-specified struct tag matching
5070** the uentryList, return its datatype. Otherwise, returns
5071** ctype_undefined.
5072*/
5073
5074ctype
5075usymtab_structFieldsType (uentryList f)
5076 /*@globals globtab@*/
5077{
5078 return (usymtab_suFieldsType (f, TRUE));
5079}
5080
5081ctype
5082usymtab_unionFieldsType (uentryList f)
5083 /*@globals globtab@*/
5084{
5085 return (usymtab_suFieldsType (f, FALSE));
5086}
5087
5088static ctype
5089usymtab_suFieldsType (uentryList f, bool isStruct)
5090 /*@globals globtab@*/
5091{
5092 int i;
5093
28bf4b0b 5094 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5095
5096 if (fileloc_isSpec (g_currentloc))
5097 {
5098 return (ctype_undefined);
5099 }
616915dd 5100
5101 for (i = 0; i < globtab->nentries; i++)
5102 {
5103 uentry current = globtab->entries[i];
5104
5105 if ((isStruct
5106 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5107 {
5108 if (isFakeTag (uentry_rawName (current)))
5109 {
5110 ctype ct = uentry_getType (current);
28bf4b0b 5111
5112 DPRINTF (("Check: %s", ctype_unparse (ct)));
616915dd 5113
5114 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
28bf4b0b 5115 &&
5116 (uentry_isSpecified (current)
5117 && uentryList_equivFields (f, ctype_getFields (ct))))
616915dd 5118 {
28bf4b0b 5119 return uentry_getAbstractType (current);
5120 }
5121 else
5122 {
5123 ;
616915dd 5124 }
5125 }
5126 }
5127 }
5128
5129 return ctype_undefined;
5130}
5131
5132ctype
5133 usymtab_enumEnumNameListType (enumNameList f)
5134 /*@globals globtab@*/
5135{
5136 int i;
5137
5138 for (i = 0; i < globtab->nentries; i++)
5139 {
5140 uentry current = globtab->entries[i];
5141
5142 if (uentry_isEnumTag (current))
5143 {
5144 if (isFakeTag (uentry_rawName (current)))
5145 {
5146 ctype ct = uentry_getType (current);
5147
5148 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5149 {
5150 return uentry_getType (current);
5151 }
5152 }
5153 }
5154 }
5155
5156 return ctype_undefined;
5157}
5158
5159bool
5160usymtab_exists (cstring k)
5161 /*@globals utab@*/
5162{
5163 uentry ce = usymtab_lookupSafe (k);
616915dd 5164 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5165}
5166
5167bool
5168usymtab_existsReal (cstring k)
5169 /*@globals utab@*/
5170{
5171 uentry ce = usymtab_lookupSafe (k);
5172
5173 return (!(uentry_isUndefined (ce))
5174 && !(uentry_isPriv (ce))
5175 && !(uentry_isExpandedMacro (ce)));
5176}
5177
5178bool
5179 usymtab_existsGlob (cstring k)
5180 /*@globals globtab@*/
5181{
5182 uentry ce = usymtab_lookupAux (globtab, k);
5183
5184 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5185}
5186
5187# ifndef NOLCL
5188bool
5189usymtab_existsEither (cstring k)
5190 /*@globals utab@*/
5191{
5192 uentry ce = usymtab_lookupAux (utab, k);
5193
5194 return (uentry_isValid (ce));
5195}
5196
5197bool
5198 usymtab_existsGlobEither (cstring k)
5199 /*@globals globtab@*/
5200{
5201 uentry ce = usymtab_lookupAux (globtab, k);
5202
5203 return (uentry_isValid (ce));
5204}
5205# endif
5206
5207bool
5208usymtab_existsType (cstring k)
5209 /*@globals globtab@*/
5210{
5211 uentry ce = usymtab_lookupAux (globtab, k);
5212
5213 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5214}
5215
5216bool
5217usymtab_existsTypeEither (cstring k)
5218 /*@globals globtab@*/
5219{
28bf4b0b 5220 uentry ce;
5221 ce = usymtab_lookupAux (globtab, k);
5222 return (uentry_isValid (ce) && uentry_isDatatype (ce));
616915dd 5223}
5224
5225bool
5226usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5227{
5228 cstring sname = makeStruct (k);
5229 uentry ce = usymtab_lookupAux (globtab, sname);
28bf4b0b 5230 cstring_free (sname);
616915dd 5231 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5232}
5233
5234bool
5235usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5236{
5237 cstring uname = makeUnion (k);
5238 uentry ce = usymtab_lookupAux (globtab, uname);
5239
5240 cstring_free (uname);
5241
5242 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5243}
5244
5245bool
5246usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5247{
5248 cstring ename = makeEnum (k);
5249 uentry ce = usymtab_lookupAux (globtab, ename);
5250
5251 cstring_free (ename);
5252 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5253}
5254
5255# ifndef NOLCL
5256bool usymtab_existsVar (cstring k)
5257 /*@globals utab@*/
5258{
5259 uentry ce = usymtab_lookupSafe (k);
5260
5261 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5262}
5263# endif
5264
5265/*
5266** destructors
5267*/
5268
5269static void
5270refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5271{
5272 if (x != NULL)
5273 {
5274 int i;
5275
5276 for (i = 0; i < nentries; i++)
5277 {
5278 sfree (x[i]);
5279 }
5280
5281 sfree (x);
5282 }
5283}
5284
5285static void
5286usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5287 /*@globals globtab, utab, filetab@*/
5288{
5289 int i;
5290
5291 aliasTable_free (u->aliases);
28bf4b0b 5292
616915dd 5293 refTable_free (u->reftable, u->nentries);
5294
5295 if (u == filetab || u == globtab)
5296 {
5297 for (i = 0; i < u->nentries; i++)
5298 {
5299 uentry_freeComplete (u->entries[i]);
5300 }
5301 }
5302 else
5303 {
5304 for (i = 0; i < u->nentries; i++)
5305 {
5306 uentry_free (u->entries[i]);
5307 }
5308 }
5309
5310 guardSet_free (u->guards);
5311 sfree (u->entries);
5312
5313 if (u != globtab
5314 && u != utab
5315 && u != filetab)
5316 {
28bf4b0b 5317 llassert (!cstringTable_isDefined (u->htable));
616915dd 5318 sfree (u);
5319 }
5320
5321/*@-mustfree@*/
5322} /*@=mustfree@*/
5323
5324static void
5325usymtab_freeAux (/*@only@*/ usymtab u)
5326 /*@globals globtab, utab, filetab@*/
5327 /*@modifies u@*/
5328{
5329 while (u != GLOBAL_ENV)
5330 {
5331 usymtab t = u->env;
5332 usymtab_freeLevel (u);
5333 u = t;
5334 /*@-branchstate@*/
5335 }
5336 /*@=branchstate@*/
5337}
5338
5339void usymtab_free ()
5340 /*@globals killed utab, globtab, filetab@*/
5341 /*@modifies utab@*/
5342{
5343 dbgfree = TRUE;
5344 usymtab_freeAux (utab);
5345}
5346
5347static int usymtab_lexicalLevel (void) /*@globals utab@*/
5348{
5349 return (utab->lexlevel);
5350}
5351
5352bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5353{
5354 return (utab == globtab);
5355}
5356
5357bool usymtab_inFileScope () /*@globals utab@*/
5358{
5359 return (utab->lexlevel == fileScope);
5360}
5361
5362bool usymtab_inFunctionScope () /*@globals utab@*/
5363{
5364 return (utab->lexlevel == functionScope);
5365}
5366
5367# ifndef NOLCL
5368void
5369usymtab_replaceEntry (uentry s)
5370 /*@globals utab, globtab@*/
5371 /*@modifies utab, s@*/
5372{
5373 usymtab_replaceEntryAux (utab, s);
5374}
5375# endif
5376
5377bool
5378usymtab_matchForwardStruct (usymId u1, usymId u2)
5379 /*@globals globtab@*/
5380{
5381 uentry ue1 = usymtab_getTypeEntry (u1);
5382 uentry ue2 = usymtab_getTypeEntry (u2);
5383
5384 if (uentry_isAnyTag (ue2))
5385 {
5386 ctype reptype = uentry_getType (ue1);
5387
5388 if (ctype_isPointer (reptype))
5389 {
5390 ctype repbase = ctype_getBaseType (reptype);
5391
5392 if (ctype_isUA (repbase))
5393 {
5394 typeId rtuid = ctype_typeId (repbase);
5395
5396 if (u2 == rtuid) return TRUE;
5397
5398 if (usymId_isValid (rtuid))
5399 {
5400 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5401
5402 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5403 }
5404 }
5405 }
5406 }
5407
5408 return FALSE;
5409}
5410
5411void usymtab_addGuards (guardSet guards)
5412 /*@modifies utab@*/
5413{
5414 utab->guards = guardSet_union (utab->guards, guards);
5415 }
5416
5417static bool usymtab_isGuardedAux (sRef s)
5418 /*@globals utab@*/
5419{
5420 usymtab tab = utab;
5421 sRef base = sRef_getRootBase (s);
5422 int lowlevel = paramsScope;
5423 int baselevel = sRef_lexLevel (base);
5424
5425 if (sRef_isCvar (base))
5426 {
5427 lowlevel = baselevel;
5428 if (lowlevel < paramsScope) lowlevel = paramsScope;
5429 }
5430
5431 while (tab->lexlevel >= lowlevel)
5432 {
2209bcb7 5433 DPRINTF (("Is guarded? [%s] %s",
5434 guardSet_unparse (tab->guards),
5435 sRef_unparseFull (s)));
5436
616915dd 5437 if (guardSet_isGuarded (tab->guards, s))
5438 {
5439 /*
5440 if (!sRef_definitelyNull (s))
5441 {
5442 sRef_setNotNull (s, fileloc_undefined);
5443 }
5444 */
5445 return TRUE;
5446 }
5447
5448 tab = usymtab_dropEnv (tab);
5449 }
5450
5451 return FALSE;
5452}
5453
5454void usymtab_unguard (sRef s) /*@modifies utab@*/
5455{
5456 usymtab tab = utab;
5457 sRef base = sRef_getRootBase (s);
5458 int lowlevel = paramsScope;
5459 int baselevel = sRef_lexLevel (base);
5460
5461 if (sRef_isCvar (base))
5462 {
5463 lowlevel = baselevel;
5464 if (lowlevel < paramsScope) lowlevel = paramsScope;
5465 }
5466
5467 while (tab->lexlevel >= lowlevel)
5468 {
5469 if (guardSet_isGuarded (tab->guards, s))
5470 {
5471 guardSet_delete (tab->guards, s);
5472 }
5473
5474 tab = usymtab_dropEnv (tab);
5475 }
5476}
5477
5478bool usymtab_isGuarded (sRef s)
5479{
2209bcb7 5480 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
616915dd 5481 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5482}
5483
28bf4b0b 5484bool usymtab_isDefinitelyNull (sRef s)
616915dd 5485{
28bf4b0b 5486 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
616915dd 5487}
5488
28bf4b0b 5489bool usymtab_isDefinitelyNullDeep (sRef s)
616915dd 5490{
28bf4b0b 5491 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
616915dd 5492}
5493
28bf4b0b 5494static bool usymtab_isDefinitelyNullAux (sRef s)
616915dd 5495 /*@globals utab@*/
5496{
5497 usymtab tab = utab;
5498 sRef base = sRef_getRootBase (s);
5499 int lowlevel = paramsScope;
5500
5501 if (sRef_isCvar (base))
5502 {
5503 lowlevel = sRef_lexLevel (base);
5504 if (lowlevel < paramsScope) lowlevel = paramsScope;
5505 }
5506
5507 while (tab->lexlevel >= lowlevel)
5508 {
28bf4b0b 5509 if (guardSet_mustBeNull (tab->guards, s))
616915dd 5510 {
5511 return TRUE;
5512 }
5513
5514 while (tab->kind == US_CBRANCH)
5515 {
5516 tab = tab->env;
5517 }
5518
5519 llassert (usymtab_isDefined (tab));
5520
5521 if (tab->kind == US_FBRANCH)
5522 {
5523 tab = tab->env;
5524 llassert (tab->kind == US_TBRANCH);
5525 }
5526
5527 tab = tab->env;
5528 }
5529
5530 return FALSE;
5531}
5532
5533void
5534usymtab_printGuards ()
5535 /*@globals utab, globtab@*/
5536{
5537 usymtab ttab = utab;
5538
5539 while (ttab != globtab)
5540 {
5541 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5542 guardSet_unparse (ttab->guards)));
5543 ttab = ttab->env;
5544 }
5545}
5546
5547void
5548usymtab_displayAllUses ()
5549 /*@globals utab, globtab@*/
5550{
5551 usymtab copy;
5552
5553 /* only in top scope */
5554 llassert (utab == globtab);
5555
5556 /* need a copy, so order is not messed up by sort! */
5557 copy = usymtab_shallowCopy (globtab);
5558
5559 qsort (copy->entries, (size_t)copy->nentries,
5560 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5561
5562 usymtab_entries (copy, ue)
5563 {
5564 if (uentry_isValid (ue))
5565 {
5566 filelocList uses = uentry_getUses (ue);
5567 int size = filelocList_realSize (uses);
5568
5569 if (fileloc_isDefined (uentry_whereDefined (ue))
5570 && !fileloc_isLib (uentry_whereDefined (ue))
5571 && (size > 0))
5572 {
28bf4b0b 5573 llmsg (message ("%q (%q), %d use%&:\n %q",
616915dd 5574 uentry_getName (ue),
5575 fileloc_unparse (uentry_whereDefined (ue)),
5576 size, filelocList_unparseUses (uses)));
5577 }
5578 }
5579 } end_usymtab_entries;
5580
5581 usymtab_shallowFree (copy);
5582}
5583
5584static /*@dependent@*/ /*@exposed@*/ usymtab
5585usymtab_getFileTab ()
5586 /*@globals filetab@*/
5587{
5588 llassert (filetab != NULL);
5589
5590 return filetab;
5591}
5592
5593/*@only@*/ cstring
5594usymtab_unparseStack ()
5595 /*@globals utab@*/
5596{
5597 return (usymtab_unparseStackTab (utab));
5598}
5599
5600static /*@only@*/ cstring
5601usymtab_unparseStackTab (usymtab t)
5602{
5603 bool firstOne = TRUE;
5604 cstring ret = cstring_makeLiteral ("[");
5605
5606 while (t != GLOBAL_ENV)
5607 {
5608 if (firstOne)
5609 {
5610 ret = message ("%q %q", ret, usymtab_typeName (t));
5611 firstOne = FALSE;
5612 }
5613 else
5614 {
5615 ret = message ("%q, %q", ret, usymtab_typeName (t));
5616 }
5617 t = t->env;
5618 }
5619
5620 ret = message ("%q ]", ret);
5621 return ret;
5622}
5623
5624static /*@only@*/ cstring
5625usymtab_typeName (/*@notnull@*/ usymtab t)
5626{
5627 switch (t->kind)
5628 {
5629 case US_GLOBAL: return cstring_makeLiteral ("global");
5630 case US_NORMAL: return cstring_makeLiteral ("normal");
5631 case US_TBRANCH: return cstring_makeLiteral ("true");
5632 case US_FBRANCH: return cstring_makeLiteral ("false");
5633 case US_CBRANCH: return cstring_makeLiteral ("case");
5634 case US_SWITCH: return cstring_makeLiteral ("switch");
5635 }
5636
5637 BADEXIT;
5638}
5639
28bf4b0b 5640void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
616915dd 5641 /*@modifies utab@*/
5642{
28bf4b0b 5643 if (!sRef_similar (s, al))
616915dd 5644 {
28bf4b0b 5645 usymtab_addForceMustAlias (s, al);
616915dd 5646 }
5647}
5648
5649/*
5650** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5651*/
5652
28bf4b0b 5653void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
616915dd 5654 /*@modifies utab@*/
5655{
5656 if (sRef_isMeaningful (s)
5657 && sRef_isMeaningful (al)
5658 && !(sRef_isConst (s) || sRef_isConst (al))
5659 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5660 {
5661 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5662 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5663
5664 /*
5665 ** for local variable, aliasing is symmetric
5666 */
5667
5668 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5669 {
5670 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5671 }
5672 }
5673 else
5674 {
5675 ;
5676 }
5677}
5678
5679void usymtab_clearAlias (sRef s)
5680 /*@modifies utab, s@*/
5681{
5682
5683 aliasTable_clearAliases (utab->aliases, s);
5684}
5685
5686sRefSet usymtab_allAliases (sRef s)
5687 /*@globals utab@*/
5688{
5689 if (sRef_isMeaningful (s))
5690 {
5691 sRefSet ret;
616915dd 5692
5693 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5694 aliasTable_canAlias (utab->aliases, s));
28bf4b0b 5695 return (ret);
616915dd 5696 }
5697 else
5698 {
28bf4b0b 5699 DPRINTF (("NOT A MEANINGFUL SREF!"));
616915dd 5700 return sRefSet_undefined;
5701 }
5702}
5703
5704/*@only@*/ sRefSet usymtab_canAlias (sRef s)
28bf4b0b 5705 /*@globals utab@*/
616915dd 5706{
5707 if (sRef_isMeaningful (s))
5708 {
5709 sRefSet res = aliasTable_canAlias (utab->aliases, s);
616915dd 5710 return res;
5711 }
28bf4b0b 5712
616915dd 5713 return sRefSet_undefined;
5714}
5715
5716/*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
28bf4b0b 5717 /*@globals utab@*/
616915dd 5718{
5719 return (aliasTable_aliasedBy (utab->aliases, s));
5720}
5721
5722/*@only@*/ cstring usymtab_unparseAliases ()
5723 /*@globals utab@*/
5724{
5725 return (aliasTable_unparse (utab->aliases));
5726}
5727
5728/*
5729** Debugging routines:
5730** okay to leak storage here, only for debugging
5731*/
5732
5733/*@-mustfree@*/
5734
5735void
5736usymtab_printOut (void)
5737 /*@globals utab@*/
5738{
5739 int i;
5740 usymtab s = utab;
5741 int depth = 0;
5742 char *ind = mstring_copy (" ");
5743
5744 fprintf (g_msgstream, "<<< [symbol table] >>>\n");
5745
5746 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5747 {
5748 cstring tname = usymtab_typeName (s);
5749
5750 if (depth < 5)
5751 {
5752 ind[depth * 3 + 1] = '\0';
5753 }
5754
5755 fprintf (g_msgstream, "level: %d (%s)\n", s->lexlevel,
5756 cstring_toCharsSafe (tname));
5757
5758 cstring_free (tname);
5759
5760 for (i = 0; i < s->nentries; i++)
5761 {
5762 cstring us = uentry_unparseFull (s->entries[i]);
5763 fprintf (g_msgstream, "%s\n", cstring_toCharsSafe (us));
5764 cstring_free (us);
5765 }
5766
5767 if (s->reftable != NULL && s->nentries > 0)
5768 {
5769 fprintf (g_msgstream, "\t<< Ref table >>\n");
5770
5771 for (i = 0; i < s->nentries; i++)
5772 {
5773 fprintf (g_msgstream, "\t%s %3d: %d, %d\n", ind, i,
5774 s->reftable[i]->level,
5775 s->reftable[i]->index);
5776 }
5777 }
5778
5779 ind[depth * 3 + 1] = ' ';
5780 depth++;
5781 s = s->env;
5782 }
5783 fprintf (g_msgstream, "<<< end usymtab >>>\n");
5784 mstring_free (ind);
5785 return;
5786}
5787
5788void
5789usymtab_printTypes ()
5790 /*@globals globtab@*/
5791{
5792 usymtab_printAllAux (globtab);
5793}
5794
5795void
5796usymtab_printAll (void)
5797 /*@globals utab@*/
5798{
5799 usymtab_printAllAux (utab);
5800}
5801
5802static void
5803usymtab_printAllAux (usymtab s)
5804 /*@modifies g_msgstream@*/
5805{
5806 int i;
5807 int depth = 0;
5808 char *ind = mstring_copy (" ");
5809
5810 printf ("[[[ usymtab ]]]");
5811
5812 while (s != GLOBAL_ENV)
5813 {
5814 if (depth < 5)
5815 ind[depth * 3 + 1] = '\0';
5816
5817 if (s->env == GLOBAL_ENV)
5818 {
5819 int looplow;
5820
5821 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5822 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5823 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5824
5825 looplow = 0;
5826
5827 for (i = looplow; i < s->nentries; i++)
5828 {
5829 printf ("%s%3d. %s\n", ind, i,
5830 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5831 }
5832 }
5833 else
5834 {
5835 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5836 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5837 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5838
5839 for (i = 0; i < s->nentries; i++)
5840 {
5841 printf ("%s%3d %s\n", ind, i,
5842 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5843 }
5844 }
5845
5846 ind[depth * 3 + 1] = ' ';
5847 depth++;
5848 s = s->env;
5849 }
5850 printf ("----------\n");
5851}
5852
5853void
5854usymtab_printComplete ()
5855 /*@globals utab@*/
5856{
5857 int i;
5858 int depth = 0;
5859 char *ind = mstring_copy (" ");
5860 usymtab s = utab;
5861
5862 while (s != GLOBAL_ENV)
5863 {
5864 if (depth < 5)
5865 {
5866 ind[depth * 3 + 1] = '\0';
5867 }
5868
5869 if (s->env == GLOBAL_ENV)
5870 {
5871 int looplow;
5872
5873 printf ("level: %d\n", s->lexlevel);
5874
5875 looplow = 0;
5876
5877 for (i = looplow; i < s->nentries; i++)
5878 {
5879 printf ("%s%3d %s\n", ind, i,
5880 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5881 }
5882 }
5883 else
5884 {
5885 printf ("level: %d\n", s->lexlevel);
5886 for (i = 0; i < s->nentries; i++)
5887 {
5888 printf ("%s%3d %s\n", ind, i,
5889 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5890 }
5891 }
5892
5893 ind[depth * 3 + 1] = ' ';
5894 depth++;
5895 s = s->env;
5896 }
5897
5898 printf ("----------\n");
5899 mstring_free (ind);
5900}
5901
3e3ec469 5902# ifdef S_SPLINT_S
616915dd 5903static /*@only@*/ cstring /*@unused@*/
5904usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5905{
5906 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5907 int i;
5908
5909 for (i = 0; i < s->nentries; i++)
5910 {
5911 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5912 }
5913
5914 c = message ("%q\n=========", c);
5915 return (c);
5916}
5917
5918static cstring /*@unused@*/ /*@only@*/
5919usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5920{
5921 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5922 bool_unparse (s->mustBreak),
5923 exitkind_unparse (s->exitCode));
5924 int i;
5925
5926 for (i = 0; i < s->nentries; i++)
5927 {
5928 sRef sr = uentry_getSref (s->entries[i]);
5929
5930 if (i == 0)
5931 {
5932 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
5933 sRef_isStateDefined (sr));
5934 }
5935 else
5936 {
5937 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
5938 sRef_isStateDefined (sr));
5939 }
5940
5941 }
5942
5943 return (c);
5944}
8250fa4a 5945# endif
616915dd 5946
5947void
5948usymtab_printLocal (void)
5949 /*@globals utab@*/
5950{
5951 int i;
5952 usymtab s = utab;
5953
5954 printf ("lexlevel: %d\n", s->lexlevel);
5955
5956 for (i = 0; i < s->nentries; i++)
5957 {
5958 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5959 }
5960
5961 while (s->lexlevel > 1)
5962 {
5963 s = s->env;
5964 }
5965
5966 llassert (usymtab_isDefined (s));
5967
5968 printf ("Params:\n");
5969
5970 for (i = 0; i < s->nentries; i++)
5971 {
5972 printf ("%d: %s\n", i,
5973 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5974 }
5975}
5976/*@=mustfree@*/
5977
5978static bool checkDistinctExternalName (uentry e)
5979 /*@globals globtab@*/
5980 /*@modifies *g_msgstream@*/
5981{
5982 int checklen = context_getValue (FLG_EXTERNALNAMELEN);
5983 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
5984 bool gotone = FALSE;
5985 bool extras = FALSE;
5986 bool hasError = FALSE;
5987 cstring name = uentry_rawName (e);
5988 usymtab st = globtab;
5989
5990 if (checklen == 0)
5991 {
5992 ;
5993 }
5994 else
5995 {
5996 if (uentry_isAnyTag (e))
5997 {
5998 checklen++; /* the tag marker doesn't count */
5999 }
6000 }
6001
6002 usymtab_entries (st, oe)
6003 {
6004 if (uentry_sameObject (oe, e))
6005 {
6006 continue;
6007 }
6008
6009 if (checklen == 0)
6010 {
6011 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6012 {
6013 if (gotone)
6014 {
6015 extras = TRUE;
6016 break;
6017 }
6018
6019 if (optgenerror
6020 (FLG_DISTINCTEXTERNALNAMES,
6021 message
6022 ("External identifier %q is not distinguishable from %q "
6023 "because alphabetical case is ignored",
6024 uentry_getName (e),
6025 uentry_getName (oe)),
6026 uentry_whereLast (e)))
6027 {
6028 uentry_showWhereAny (oe);
6029 uentry_setHasNameError (oe);
6030 gotone = TRUE;
6031 }
6032 }
6033 }
6034 else
6035 {
6036 if (ignorecase)
6037 {
6038 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6039 name, checklen))
6040 {
6041 if (gotone)
6042 {
6043 extras = TRUE;
6044 break;
6045 }
6046
6047 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6048 {
6049 if (optgenerror
6050 (FLG_DISTINCTEXTERNALNAMES,
6051 /*@-sefparams@*/
6052 message
6053 ("External identifier %q is not distinguishable from %q "
6054 "in the first %d characters (%q)",
6055 uentry_getName (e),
6056 uentry_getName (oe),
6057 checklen,
6058 cstring_clip (uentry_getName (e), checklen)),
6059 /*@=sefparams@*/
6060 uentry_whereLast (e)))
6061 {
6062 uentry_showWhereAny (oe);
6063 uentry_setHasNameError (oe);
6064 gotone = TRUE;
6065 }
6066 }
6067 else
6068 {
6069 if (gotone)
6070 {
6071 extras = TRUE;
6072 break;
6073 }
6074
6075 if (optgenerror
6076 (FLG_DISTINCTEXTERNALNAMES,
6077 message
6078 ("External identifier %q is not distinguishable from %q "
6079 "in the first %d characters because alphabetical case "
6080 "is ignored",
6081 uentry_getName (e),
6082 uentry_getName (oe),
6083 checklen),
6084 uentry_whereLast (e)))
6085 {
6086 uentry_showWhereAny (oe);
6087 uentry_setHasNameError (oe);
6088 gotone = TRUE;
6089 }
6090 }
6091 }
6092 }
6093 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6094 {
6095 if (gotone)
6096 {
6097 extras = TRUE;
6098 break;
6099 }
6100
6101 if (optgenerror
6102 (FLG_DISTINCTEXTERNALNAMES,
6103 /*@-sefparams@*/
6104 message
6105 ("External identifier %q is not distinguishable from %q "
6106 "in the first %d characters (%q)",
6107 uentry_getName (e),
6108 uentry_getName (oe),
6109 checklen,
6110 cstring_clip (uentry_getName (e), checklen)),
6111 /*@=sefparams@*/
6112 uentry_whereLast (e)))
6113 {
6114 uentry_showWhereAny (oe);
6115 uentry_setHasNameError (oe);
6116 gotone = TRUE;
6117 }
6118 }
6119 else
6120 {
6121 ; /* okay */
6122 }
6123 }
6124 } end_usymtab_entries ;
6125
6126 hasError = gotone;
6127
6128 if (extras)
6129 {
6130 llgenindentmsgnoloc
6131 (cstring_makeLiteral ("One or more additional "
6132 "indistinguishable external "
6133 "names not reported"));
6134 }
6135
6136 return hasError;
6137}
6138
6139static bool checkDistinctInternalName (uentry e)
6140 /*@globals utab@*/
6141 /*@modifies *g_msgstream@*/
6142{
6143 usymtab ttab = utab;
6144 cstring name = uentry_rawName (e);
6145 int numchars = context_getValue (FLG_INTERNALNAMELEN);
6146 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6147 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6148
6149 if (uentry_isAnyTag (e) && (numchars != 0))
6150 {
6151 numchars++; /* the tag marker doesn't count */
6152 }
6153
6154 while (usymtab_isDefined (ttab))
6155 {
6156 usymtab_entries (ttab, oe)
6157 {
6158 if (uentry_sameObject (oe, e))
6159 {
6160 /*@innercontinue@*/ continue;
6161 }
6162
6163 switch (cstring_genericEqual
6164 (name, uentry_rawName (oe),
6165 numchars, caseinsensitive, lookalike))
6166 {
6167 case CGE_DISTINCT: /* okay */
6168 /*@switchbreak@*/
6169 break;
6170 case CGE_SAME:
6171 if (cstring_equal (name, uentry_rawName (oe)))
6172 {
6173 ; /* got a shadow error */
6174 }
6175 else
6176 {
6177 if (optgenerror
6178 (FLG_DISTINCTINTERNALNAMES,
6179 /*@-sefparams@*/
6180 message
6181 ("Internal identifier %q is not distinguishable from %q "
6182 "in the first %d characters (%q)",
6183 uentry_getName (e),
6184 uentry_getName (oe),
6185 numchars,
6186 cstring_clip (uentry_getName (e), numchars)),
6187 /*@=sefparams@*/
6188 uentry_whereLast (e)))
6189 {
6190 uentry_showWhereAny (oe);
6191 uentry_setHasNameError (oe);
6192 return TRUE;
6193 }
6194 }
6195 /*@switchbreak@*/
6196 break;
6197 case CGE_CASE:
6198 if (numchars == 0
6199 || (cstring_length (name) <= numchars))
6200 {
6201 if (optgenerror
6202 (FLG_DISTINCTINTERNALNAMES,
6203 message
6204 ("Internal identifier %q is not distinguishable from %q "
6205 "without case sensitivity",
6206 uentry_getName (e),
6207 uentry_getName (oe)),
6208 uentry_whereLast (e)))
6209 {
6210 uentry_showWhereAny (oe);
6211 uentry_setHasNameError (oe);
6212 return TRUE;
6213 }
6214 }
6215 else
6216 {
6217 if (optgenerror
6218 (FLG_DISTINCTINTERNALNAMES,
6219 message
6220 ("Internal identifier %q is not distinguishable from %q "
6221 "in the first %d characters without case sensitivity",
6222 uentry_getName (e),
6223 uentry_getName (oe),
6224 numchars),
6225 uentry_whereLast (e)))
6226 {
6227 uentry_showWhereAny (oe);
6228 uentry_setHasNameError (oe);
6229 return TRUE;
6230 }
6231 }
6232 /*@switchbreak@*/
6233 break;
6234 case CGE_LOOKALIKE:
6235 if (numchars == 0
6236 || (cstring_length (name) <= numchars))
6237 {
6238 if (optgenerror
6239 (FLG_DISTINCTINTERNALNAMES,
6240 message
6241 ("Internal identifier %q is not distinguishable from %q "
6242 "except by lookalike characters",
6243 uentry_getName (e),
6244 uentry_getName (oe)),
6245 uentry_whereLast (e)))
6246 {
6247 uentry_showWhereAny (oe);
6248 uentry_setHasNameError (oe);
6249 return TRUE;
6250 }
6251 }
6252 else
6253 {
6254 if (optgenerror
6255 (FLG_DISTINCTINTERNALNAMES,
6256 message
6257 ("Internal identifier %q is not distinguishable from %q "
6258 "in the first %d characters except by lookalike characters",
6259 uentry_getName (e),
6260 uentry_getName (oe),
6261 numchars),
6262 uentry_whereLast (e)))
6263 {
6264 uentry_showWhereAny (oe);
6265 uentry_setHasNameError (oe);
6266 return TRUE;
6267 }
6268 }
6269 }
6270 } end_usymtab_entries ;
6271
6272 ttab = ttab->env;
6273 }
6274
6275 return FALSE;
6276}
6277
6278void usymtab_checkDistinctName (uentry e, int scope)
6279 /*@globals utab, globtab@*/
6280{
6281 bool hasError = FALSE;
6282 fileloc where = uentry_whereLast (e);
6283
6284 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6285 {
6286 if (scope == globScope)
6287 {
6288 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6289 {
6290 hasError = checkDistinctExternalName (e);
6291 }
6292 }
6293
6294 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6295 {
6296 hasError = checkDistinctInternalName (e);
6297 }
6298 }
6299
6300 if (hasError)
6301 {
28bf4b0b 6302 uentry_setHasNameError (e);
616915dd 6303 }
6304}
6305
28bf4b0b 6306/*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6307{
6308 uentry ue;
6309
6310 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6311 llassert (uentry_isValid (ue));
6312
6313 return uentry_getSref (ue);
6314}
6315
This page took 1.520897 seconds and 5 git commands to generate.