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