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