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