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