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