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