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