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