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