]> andersk Git - splint.git/blame - src/usymtab.c
Updating to use the LEnsures and LRequires instead of the ensures requires so
[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 }
920a3797 1583
1584 lastekind = KINVALID;
1585
1586 fprintf(fout, ";; Library constraints\n");
1587 for (i = 0; i < utab->nentries; i++)
1588 {
1589 uentry thisentry = utab->entries[i];
1590
1591 if (uentry_isFunction (thisentry) )
1592 {
1593 constraintList preconditions;
1594 constraintList postconditions;
1595
1596 preconditions = uentry_getFcnPreconditions (thisentry);
1597 postconditions = uentry_getFcnPostconditions (thisentry);
1598
1599 if ( constraintList_isDefined(preconditions) ||
1600 constraintList_isDefined(postconditions) )
1601 {
1602 fprintf(fout,"%s\n", uentry_rawName(thisentry) );
1603 if (constraintList_isDefined(preconditions) )
1604 {
1605 fprintf(fout,"pre:\n");
1606 constraintList_dump(preconditions, fout);
1607 fprintf (fout, ";; end precondition constraints\n" );
1608 constraintList_free(preconditions);
1609 }
1610 else
1611 {
1612 fprintf(fout,"pre:EMPTY\n");
1613 }
1614 if (constraintList_isDefined(postconditions) )
1615 {
1616 fprintf(fout,"post:\n");
1617 constraintList_dump(postconditions, fout);
1618 fprintf (fout, ";; end precondition constraints\n" );
1619 constraintList_free(postconditions);
1620 }
1621 else
1622 {
1623 fprintf(fout,"post:EMPTY\n");
1624 }
1625 }
1626
1627 }
1628 }
1629
1630
1631
616915dd 1632}
1633
1634void usymtab_load (FILE *f)
1635 /*@globals utab, globtab@*/
1636 /*@modifies utab, *f@*/
1637{
1638 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1639 char *os = s;
1640 ekind kind = KINVALID;
1641 fileloc loc = g_currentloc;
1642 char c;
1643 uentry ue;
1644
1645 dbgload = TRUE;
1646
1647 llassert (utab == globtab);
1648 llassert (utab->nentries == 0);
1649
1650 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
1651 && *s == ';')
1652 {
1653 ; /* ignore ;-comments */
1654 }
1655
1656 while (s != NULL && *s != ';')
1657 {
1658
1659 if (*s == '*')
1660 {
1661 s++;
1662 kind = ekind_fromInt (getInt (&s));
1663
1664 goto nextiter;
1665 }
1666
1667 if (*s == '$')
1668 {
1669 llfatalerror
1670 (cstring_makeLiteral
1671 ("Library is in obsolete format. Use lclint +whichlib "
1672 "to see which library is being loaded."));
1673 }
1674
1675 ue = uentry_undump (kind, loc, &s);
1676 DPRINTF (("Load: %s", uentry_unparseFull (ue)));
1677
1678 if (uentry_isValid (ue))
1679 {
1680 ue = usymtab_addEntryBase (utab, ue);
1681 /*@-branchstate@*/
1682 }
1683 /*@=branchstate@*/
1684
1685 /*
1686 ** now, any other names are the same uentry
1687 */
1688
1689 while (*(s++) == '#')
1690 {
1691 cstring name = cstring_fromCharsO (getWord (&s));
1692 uentry nue = uentry_nameCopy (name, ue);
1693
1694 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1695 usymtab_addEntryBase (utab, nue);
1696 }
1697
1698 while ((c = *s) != '\0' && (c !='\n'))
1699 {
1700 if (c != ' ' || c != '\t')
1701 {
1702 llbuglit ("Junk in load file");
1703 }
1704
1705 s++;
1706 }
1707
1708 nextiter:
1709 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1710 }
1711
920a3797 1712 /*DRL added 6/21/01
1713 to handle reading of buffer overflow related constraints
1714 */
1715 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
1716 && *s == ';')
1717 {
1718 ; /* ignore ;-comments */
1719 }
1720
1721 while (s != NULL && *s != ';')
1722 {
1723 constraintList preconditions;
1724 constraintList postconditions;
1725
1726 cstring name = getWord(&s);
1727 cstring temp;
1728 ue = usymtab_lookup ( name );
1729
1730 cstring_free(name);
1731
1732 preconditions = constraintList_undefined;
1733 postconditions = constraintList_undefined;
1734
1735 if (!uentry_isValid(ue) )
1736 {
1737 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", s) ));
1738 }
1739 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1740
1741 temp = getWord(&s);
1742
1743 if (cstring_compare (temp,"pre:") == 0 )
1744 {
1745 preconditions = constraintList_undump(f);
1746 }
1747 cstring_free(temp);
1748
1749 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1750
1751 temp = getWord(&s);
1752 if (cstring_compare (temp,"post:") == 0 )
1753 {
1754 postconditions = constraintList_undump(f);
1755 }
1756
1757 cstring_free(temp);
1758
1759 uentry_setPreconditions (ue, preconditions);
1760 uentry_setPostconditions (ue, postconditions);
1761
1762 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1763 }
1764
616915dd 1765 dbgload = FALSE;
1766 sfree (os);
1767}
1768
1769/*
1770** file scope for static variables
1771*/
1772
1773void
1774usymtab_enterFile ()
1775 /*@globals utab, globtab, filetab@*/
1776 /*@modifies filetab@*/
1777{
1778 llassert (utab == globtab);
1779
1780 # if 0
1781 /* check globals */
1782
1783 usymtab_entries (globtab, ue)
1784 {
1785 if (sRef_hasDerived (uentry_getSref (ue)))
1786 {
1787 fprintf (g_msgstream, "Derived Global: %s\n", uentry_unparse (ue));
1788 fprintf (g_msgstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
1789 }
1790 } end_usymtab_entries ;
1791
1792 # endif
1793
1794 usymtab_enterScope ();
1795 filetab = utab;
1796}
1797
1798void
1799usymtab_exitFile ()
1800 /*@globals utab, filetab@*/
1801 /*@modifies filetab, utab@*/
1802{
1803
1804 llassert (utab->lexlevel == 1);
1805
1806 usymtab_exitScope (exprNode_undefined);
1807 filetab = NULL;
1808}
1809
1810void
1811usymtab_enterScope ()
1812 /*@globals utab, globtab, filetab@*/
1813 /*@modifies utab@*/
1814{
1815 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
1816
1817 /* unconditional scope: optimize to avoid copy */
1818 t->aliases = aliasTable_copy (utab->aliases);
1819 utab = t;
1820
1821 llassert (usymtab_isDefined (t->env));
1822
1823 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
1824 {
1825 noshadowerror = TRUE;
1826 usymtab_handleParams ();
1827 noshadowerror = FALSE;
1828 }
1829}
1830
1831/*
1832** setup external references:
1833** o only, unique params alias external args
1834** o other params may alias anything of their type
1835*/
1836
1837static void
1838usymtab_handleParams (void)
1839 /*@globals utab, globtab, filetab@*/
1840 /*@modifies utab, globtab@*/
1841{
1842 usymtab ptab = utab->env;
1843 uentry fcn = context_getHeader ();
1844
1845
1846 usymtab_entries (ptab, param)
1847 {
1848 uentry ue;
1849
1850 if (!uentry_isYield (param))
1851 {
1852 sRef uref;
1853 sRef pref = uentry_getSref (param);
1854
1855 llassertprint (uentry_isAnyParam (param),
1856 ("not param: %s",
1857 uentry_unparseFull (param)));
1858
1859
1860 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
1861 uentry_getType (param),
1862 fileloc_copy (uentry_whereDeclared (param)),
1863 FALSE);
1864
1865 uentry_copyState (ue, param);
1866 uentry_setRefParam (ue);
1867
1868 ue = usymtab_supEntrySrefReturn (ue);
1869
1870 /* must be after supercede! */
1871
1872 if (!sRef_stateKnown (pref))
1873 {
1874 uentry_setDefState (ue, SS_DEFINED);
1875 uentry_setDefState (param, SS_DEFINED);
1876 }
1877 else
1878 {
1879 if (sRef_isStateSpecial (pref))
1880 {
1881 uentry_setDefState (ue, SS_ALLOCATED);
1882 }
1883 else
1884 {
1885 uentry_setDefState (ue, sRef_getDefState (pref));
1886 }
1887 }
1888
1889 uref = uentry_getSref (ue);
1890
1891 if (sRef_isStack (uref))
1892 {
1893 alkind pkind = sRef_getAliasKind (pref);
1894
1895 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
1896 && !alkind_isStack (pkind))
1897 {
1898 sRef_setAliasKind (uref, pkind, fileloc_undefined);
1899 sRef_setOrigAliasKind (uref, pkind);
1900 }
1901 else
1902 {
1903 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
1904 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
1905
1906 if (uentry_isOut (param))
1907 {
1908 ;
1909 }
1910 else
1911 {
1912 sRef_setDefined (uref, fileloc_undefined);
1913 }
1914 }
1915
1916 }
1917
1918 usymtab_addMustAlias (uref, pref);
1919
1920 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
1921 {
1922 sRef s = sRef_makeExternal (uref);
1923
1924 usymtab_addMustAlias (uref, s);
1925 }
1926
1927 if (sRef_isKillRef (pref))
1928 {
1929 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
1930 sRef_setOrigAliasKind (uref, AK_KILLREF);
1931 }
1932 else if (sRef_isRefCounted (uref))
1933 {
1934 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
1935 }
1936 else
1937 {
1938 /* was AK_UNIQUE */
1939 sRef_setOrigAliasKind (uref, AK_LOCAL);
1940 }
1941 }
1942 else
1943 {
1944 }
1945 } end_usymtab_entries;
1946
1947
1948 if (uentry_hasSpecialClauses (fcn))
1949 {
1950 specialClauses clauses = uentry_getSpecialClauses (fcn);
1951
1952 specialClauses_preElements (clauses, cl)
1953 {
1954 sRefSet refs = specialClause_getRefs (cl);
1955 sRefMod modf = specialClause_getEntryFunction (cl);
1956
1957
1958 sRefSet_elements (refs, el)
1959 {
1960 sRef base = sRef_getRootBase (el);
1961
1962 if (sRef_isResult (base))
1963 {
1964 ; /* nothing to do before */
1965 }
1966 else if (sRef_isParam (base))
1967 {
1968 if (modf != NULL)
1969 {
1970 sRef sb = sRef_updateSref (el);
1971 sRefSet aliases = usymtab_allAliases (sb);
1972
1973 modf (sb, fileloc_undefined);
1974
1975 sRefSet_elements (aliases, sr)
1976 {
1977 modf (sr, fileloc_undefined);
1978 } end_sRefSet_elements ;
1979
1980 sRefSet_free (aliases);
1981 }
1982 }
1983 else
1984 {
1985 if (sRef_isValid (base))
1986 {
1987 BADBRANCH;
1988 }
1989 }
1990 } end_sRefSet_elements ;
1991 } end_specialClauses_preElements ;
1992 }
1993 }
1994
1995void
1996usymtab_enterFunctionScope (uentry fcn)
1997 /*@globals utab, filetab, globtab@*/
1998 /*@modifies utab@*/
1999{
2000 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2001
2002 if (utab->lexlevel != fileScope)
2003 {
2004 if (utab->lexlevel > fileScope)
2005 {
2006 llparseerror (cstring_makeLiteral ("New function scope inside function."));
2007
2008 while (utab->lexlevel > fileScope)
2009 {
2010 /*@i@*/ utab = usymtab_dropEnv (utab);
2011 /*@-branchstate@*/
2012 }
2013 /*@=branchstate@*/
2014 }
2015 else
2016 {
2017 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2018 }
2019 /*@-branchstate@*/ } /*@=branchstate@*/
2020
2021 globSet_allElements (uentry_getGlobs (fcn), el)
2022 {
2023
2024 if (sRef_isUndefGlob (el))
2025 {
2026 int index = sRef_getScopeIndex (el);
2027 sRef sr = sRef_updateSref (el);
2028 fileloc loc = uentry_whereEarliest (fcn);
2029
2030 if (sRef_isFileStatic (el))
2031 {
2032 ctype ct = sRef_getType (el);
2033 uentry ue;
2034
2035 llassert (usymtab_isDefined (filetab));
2036
2037 ue = usymtab_fetchIndex (filetab, index);
2038
2039 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2040 {
2041 sRef_setAllocated (sr, loc);
2042 }
2043 else
2044 {
2045 sRef_setUndefined (sr, loc);
2046 }
2047 }
2048 else
2049 {
2050 uentry ue = globtab->entries[index];
2051 ctype ct = uentry_getType (ue);
2052
2053 if (ctype_isArray (ct) || ctype_isSU (ct))
2054 {
2055 sRef_setAllocated (sr, loc);
2056 }
2057 else
2058 {
2059 sRef_setUndefined (sr, loc);
2060 }
2061 }
2062 }
2063 else if (sRef_isAllocated (el))
2064 {
2065 sRef sr = sRef_updateSref (el);
2066 fileloc loc = uentry_whereEarliest (fcn);
2067
2068 sRef_setAllocated (sr, loc);
2069 }
2070 else if (sRef_isPartial (el))
2071 {
2072 sRef sr = sRef_updateSref (el);
2073 fileloc loc = uentry_whereEarliest (fcn);
2074
2075 sRef_setPartial (sr, loc);
2076 }
2077 else
2078 {
2079 /* defined */ ;
2080 }
2081 } end_globSet_allElements;
2082
2083 utab = t;
2084}
2085
2086static void
2087usymtab_caseBranch (void)
2088 /*@modifies utab@*/
2089{
2090 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2091 utab = t;
2092}
2093
2094void
2095usymtab_switchBranch (/*@unused@*/ exprNode s)
2096 /*@modifies utab@*/
2097{
2098 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2099
2100 t->aliases = aliasTable_copy (utab->aliases);
2101 utab = t;
2102}
2103
2104void
2105usymtab_trueBranch (/*@only@*/ guardSet guards)
2106 /*@modifies utab@*/
2107{
2108 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2109
2110 /*
2111 ** not true! (could be in a macro)
2112 **
2113 ** llassertprint (utab->lexlevel > paramsScope,
2114 ** ("not in scope: %s", usymtab_unparseLocal ()));
2115 **
2116 */
2117
2118 guardSet_free (t->guards);
2119 t->guards = guards;
2120
2121 aliasTable_free (t->aliases);
2122 t->aliases = aliasTable_copy (utab->aliases);
2123
2124 utab = t;
2125}
2126
2127/*
2128** consider,
2129**
2130** { int a; if (...) a = 3; < a may be undefined here!
2131**
2132*/
2133
2134void
2135usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl)
2136{
2137 /*
2138 ** add a false branch
2139 ** (could be done more efficiently as a special case, but
2140 ** it is better to only maintain one version of the code)
2141 */
2142
2143 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2144 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2145}
2146
2147void
2148usymtab_popCaseBranch () /*@modifies utab@*/
2149{
2150 llassert (utab->kind == US_CBRANCH);
2151 usymtab_quietPlainExitScope ();
2152}
2153
2154void
2155usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2156{
2157 /*
2158 ** add a false branch that must return --- that is,
2159 ** the true branch is always executed!
2160 */
2161
2162 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2163 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2164}
2165
2166void
2167usymtab_popOrBranch (exprNode pred, exprNode expr)
2168 /*@modifies utab@*/
2169{
2170 bool mustReturn;
2171 usymtab env = utab->env;
2172 usymtab otab = utab;
2173 int i = 0;
2174
2175 llassert (env != NULL);
2176
2177 if (exprNode_isError (expr))
2178 {
2179 mustReturn = FALSE;
2180 }
2181 else
2182 {
2183 mustReturn = exprNode_mustEscape (expr);
2184 }
2185
2186
2187 llassert (utab->kind == US_TBRANCH);
2188
2189 /*
2190 ** merge each entry in table with its original
2191 ** unless execution cannot continue after this branch
2192 */
2193
2194 for (i = 0; i < utab->nentries; i++)
2195 {
2196 uentry current = utab->entries[i];
2197 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2198
2199 uentry_mergeState (old, current, exprNode_loc (expr),
2200 mustReturn, FALSE, TRUE, ORCLAUSE);
2201 }
2202
2203
2204 if (mustReturn)
2205 {
2206 env->guards = guardSet_levelUnionFree (env->guards,
2207 guardSet_invert (exprNode_getGuards (pred)),
2208 env->lexlevel);
2209 }
2210 else
2211 {
2212 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2213 }
2214
2215 /* env is now utab */
2216 usymtab_quietPlainExitScope ();
2217}
2218
2219/*
2220** case syntax in C is very unrestricted. This is unfortunate.
2221**
2222** A switch case is ended either by a new case or default, or
2223** a close } that may close the switch or some other control
2224** structure.
2225*/
2226
2227bool
2228usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2229 /*@modifies utab@*/
2230{
2231 bool mustBreak = usymtab_mustBreak (utab);
2232 bool mustReturn = usymtab_mustEscape (utab);
2233 usymtab stab = utab;
2234
2235 /*
2236 ** Find last case (or outer switch)
2237 */
2238
2239 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2240 {
2241 stab = stab->env;
2242 llassert (stab != GLOBAL_ENV);
2243 }
2244
2245 /* ??? */
2246
2247 while (stab->kind == US_CBRANCH)
2248 {
2249 stab = stab->env;
2250 llassert (stab != GLOBAL_ENV);
2251 }
2252
2253 /*
2254 ** if its a fall through case, merge in outside entries and last case.
2255 **
2256 ** e.g.,
2257 ** ...
2258 ** switch
2259 ** case 1: x = 3; <fall through>
2260 ** case 2: << x may not be defined
2261 **
2262 */
2263
2264 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2265 {
2266 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2267
2268 usymtab_entries (utab, ue) /* but, keep track of used variables */
2269 {
2270 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2271
2272 llassert (uentry_isValid (old));
2273
2274 /* modifies ue, not old */
2275
2276 uentry_mergeState (ue, old, exprNode_loc (last),
2277 FALSE, FALSE, TRUE, CASECLAUSE);
2278 } end_usymtab_entries;
2279
2280 utab->aliases = aliasTable_levelUnion (utab->aliases,
2281 stab->aliases, utab->lexlevel);
2282
2283 /*
2284 ** No need for a new branch.
2285 */
2286
2287 return FALSE;
2288 }
2289 else
2290 {
2291 usymtab_caseBranch ();
2292 /*@-mustfree@*/ /*< utab->aliases >*/
2293 utab->aliases = aliasTable_copy (stab->aliases);
2294 /*@=mustfree@*/
2295
2296 return TRUE;
2297 }
2298}
2299
2300/*
2301** for && (both pred and expr are executed)
2302*/
2303
2304void
2305usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2306 /*@modifies utab@*/
2307{
2308 usymtab env = utab->env;
2309 usymtab otab= utab;
2310 int i = 0;
2311
2312 llassert (utab->kind == US_TBRANCH);
2313
2314 /*
2315 ** merge each entry in table with its original
2316 ** unless execution cannot continue after this branch
2317 */
2318
2319 for (i = 0; i < utab->nentries; i++)
2320 {
2321 uentry current = utab->entries[i];
2322 sRef tref = uentry_getSref (current);
2323 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2324 sRef oref = uentry_getSref (old);
2325
2326 /* note that is current is in a nested branch,
2327 it may create a "new" old entry. */
2328
2329 llassert (uentry_isValid (old));
2330 uentry_mergeState (old, current, exprNode_loc (expr),
2331 FALSE, FALSE, TRUE, ANDCLAUSE);
2332
2333 /*
2334 ** if is it defined by the second clause, then it should be defined.
2335 */
2336
2337 if (sRef_isAnyDefined (tref)
2338 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2339 {
2340 sRef_setDefined (oref, g_currentloc);
2341 }
2342 }
2343
2344 utab->guards = guardSet_levelUnionFree (utab->guards,
2345 guardSet_invert (exprNode_getGuards (pred)),
2346 utab->lexlevel);
2347 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2348
2349 usymtab_quietPlainExitScope ();
2350
2351 }
2352
2353/*
2354** Stack should be [ US_CBRANCH+ US_SWITCH ]
2355** Only branches which do not return (except possibly the last branch) are included.
2356**
2357** Conditionally merge state from all CBRANCHes.
2358**
2359** If allpaths is TRUE, then all possible executions go through some switch
2360** case, and the original scope is not merged.
2361*/
2362
2363void
2364usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2365 /*@modifies utab@*/
2366{
2367 usymtab ttab = utab;
2368 usymtab stab = ttab;
2369 usymtab ltab = ttab;
2370 bool lastMustReturn = usymtab_mustEscape (utab);
2371 int i;
2372
2373
2374 while (stab->kind == US_CBRANCH)
2375 {
2376 stab = stab->env;
2377 llassert (stab != GLOBAL_ENV);
2378 }
2379
2380 while (stab->kind == US_NORMAL)
2381 {
2382 stab = stab->env;
2383 llassert (stab != GLOBAL_ENV);
2384 }
2385
2386 llassert (stab->kind == US_SWITCH);
2387
2388 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2389 stab = stab->env;
2390 llassert (stab != GLOBAL_ENV);
2391
2392
2393 ttab = ttab->env;
2394 llassert (usymtab_isDefined (ttab));
2395
2396 if (ttab->kind == US_CBRANCH)
2397 {
2398 /* was quietPlainExitScope --- but, can't free it yet! */
2399 utab = utab->env;
2400 llassert (utab != GLOBAL_ENV);
2401
2402 while (ttab->kind == US_CBRANCH)
2403 {
2404 /*
2405 ** (from popTrueBranch)
2406 */
2407
2408 bool mustReturn = usymtab_mustEscape (ttab);
2409 bool mustBreak = usymtab_mustBreak (ttab);
2410
2411 usymtab_entries (ttab, current)
2412 {
2413 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2414 /*@=compmempass@*/
2415
2416 /*
2417 ** note that is this is in a nested branch,
2418 ** it may create a "new" old entry.
2419 */
2420
2421 if (uentry_isValid (old))
2422 {
2423 if (lastMustReturn)
2424 {
2425 uentry_mergeUses (current, old);
2426 uentry_setState (old, current);
2427 }
2428 else
2429 {
2430 uentry_mergeState (old, current, exprNode_loc (sw),
2431 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2432 }
2433 }
2434 else
2435 {
2436 ;
2437 }
2438 } end_usymtab_entries;
2439
2440 /*
2441 ** if entry is not in symbol table for this case, merge with pre-switch
2442 ** table
2443 */
2444
2445 if (!mustReturn && !mustBreak)
2446 {
2447 usymtab_entries (stab, current)
2448 {
2449 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2450 {
2451 uentry old = /*@-compmempass@*/
2452 usymtab_lookupAux (ltab, uentry_rawName (current));
2453 /*@=compmempass@*/
2454
2455 llassert (uentry_isValid (old));
2456 uentry_mergeState (old, current, exprNode_loc (sw),
2457 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2458 }
2459 } end_usymtab_entries;
2460 }
2461
2462 ltab->env = ttab->env;
2463 ttab = ltab->env;
2464
2465 /*
2466 ** Suprious error, becuase of environments.
2467 */
2468
2469 /*@i1@*/ utab = ltab;
2470
2471 lastMustReturn = FALSE;
2472 /*@-branchstate@*/
2473 }
2474 }
2475 /*@=branchstate@*/
2476
2477 /*
2478 ** now, there is one US_CBRANCH. Merge this with the stab.
2479 */
2480
2481
2482 for (i = 0; i < ltab->nentries; i++)
2483 {
2484 uentry current = ltab->entries[i];
2485 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2486
2487 /* note that is this is in a nested branch,
2488 it may create a "new" old entry. */
2489
2490
2491 if (uentry_isValid (old))
2492 {
2493 if (allpaths)
2494 {
2495 uentry_mergeUses (current, old);
2496 uentry_setState (old, current);
2497 }
2498 else
2499 {
2500 uentry_mergeState (old, current, exprNode_loc (sw),
2501 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2502 }
2503 }
2504 else
2505 {
2506 }
2507 }
2508
2509 /*
2510 ** exit the switch
2511 */
2512
2513
2514 /*
2515 ** switch may or may not be followed by a new scope
2516 */
2517
2518 if (utab->kind == US_SWITCH)
2519 {
2520 usymtab_quietPlainExitScope ();
2521 }
2522 else
2523 {
2524 usymtab_quietPlainExitScope ();
2525 llassert (utab->kind == US_SWITCH);
2526 usymtab_quietPlainExitScope ();
2527 }
2528
2529 }
2530
2531static void
2532updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2533 /*@notnull@*/ usymtab ftab, bool trueGuard)
2534{
2535 sRef base = sRef_getRootBase (el);
2536 int level = sRef_lexLevel (base);
2537
2538
2539
2540 if (sRef_isCvar (base))
2541 {
2542 usymId index = sRef_getScopeIndex (base);
2543 uentry ue = usymtab_getRefTab (ttab, level, index);
2544
2545 if (!uentry_isLset (ue))
2546 {
2547 sRef sr = uentry_getSref (ue);
2548
2549 if (trueGuard)
2550 {
2551 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2552 }
2553 else
2554 {
2555 if (!guardSet_isGuarded (ttab->guards, el)
2556 && !sRef_isNotNull (sr))
2557 {
2558 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2559 }
2560 }
2561 }
2562 else
2563 {
2564 }
2565
2566 ue = usymtab_getRefTab (ftab, level, index);
2567
2568 if (!uentry_isLset (ue))
2569 {
2570 sRef sr = uentry_getSref (ue);
2571
2572
2573 if (!trueGuard) /* yikes! forgot the ! */
2574 {
2575 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2576 }
2577 else
2578 {
2579
2580 if (!guardSet_isGuarded (ftab->guards, el)
2581 && !sRef_isNotNull (sr))
2582 {
2583 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2584 }
2585 }
2586 }
2587 else
2588 {
2589 }
2590
2591 }
2592
2593 }
2594
2595void
2596usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2597 bool isOpt, clause cl)
2598 /*@modifies utab@*/
2599{
2600 int i = 0;
2601 usymtab ftab = utab;
2602 usymtab ttab = utab->env;
2603
2604 fileloc loc;
2605 usymtab env;
2606 guardSet guards = exprNode_getGuards (pred);
2607 sRefSet tguards = guardSet_getTrueGuards (guards);
2608 sRefSet fguards = guardSet_getFalseGuards (guards);
2609 bool mustReturnT = exprNode_mustEscape (tbranch);
2610 bool mustReturnF = exprNode_mustEscape (fbranch);
2611
2612 if (exprNode_isDefined (fbranch))
2613 {
2614 loc = exprNode_loc (fbranch);
2615 }
2616 else
2617 {
2618 loc = exprNode_loc (tbranch);
2619 }
2620
2621 llassert (usymtab_isDefined (ttab));
2622
2623 env = ttab->env;
2624
2625 llassert (usymtab_isDefined (env));
2626 llassert (ftab->kind == US_FBRANCH);
2627 llassert (ttab->kind == US_TBRANCH);
2628
2629 /*
2630 ** For each element that is true guarded (i.e., if (x != NULL))
2631 ** make x = null in false branch,
2632 ** and x = notnull in true branch.
2633 ** unless x was set locally in that branch.
2634 ** For each element that is false guarded (x == NULL)
2635 ** make x = null in true, notnull in false.
2636 **
2637 ** For each element that is either guarded (pred(x))
2638 **
2639 */
2640
2641 sRefSet_allElements (tguards, el)
2642 {
2643 updateNullState (el, ttab, ftab, TRUE);
2644 } end_sRefSet_allElements;
2645
2646 sRefSet_allElements (fguards, el)
2647 {
2648 updateNullState (el, ttab, ftab, FALSE);
2649 } end_sRefSet_allElements;
2650
2651 /*
2652 **
2653 ** if an entry is in both true and false, merge the entries,
2654 ** then replace original with new state.
2655 **
2656 ** if an entry is in one table, merge it with the original.
2657 */
2658
2659 for (i = 0; i < ftab->nentries; i++)
2660 {
2661 uentry fthis = ftab->entries[i];
2662 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
2663 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
2664
2665 if (uentry_isUndefined (old))
2666 {
2667 /* possible entry was added as an undefined id */
2668 continue;
2669 }
2670
2671 if (tindex != NOT_FOUND)
2672 {
2673 uentry tthis = ttab->entries[tindex];
2674
2675 /* note that is this is in a nested branch,
2676 it may create a "new" old entry. */
2677
2678 if (!mustReturnF)
2679 {
2680 if (!mustReturnT)
2681 {
2682
2683 uentry_mergeState (fthis, tthis, loc,
2684 mustReturnT, FALSE, FALSE, cl);
2685 }
2686 else
2687 {
2688 uentry_mergeUses (fthis, tthis);
2689 }
2690
2691 uentry_setState (old, fthis);
2692
2693 /*@-mustfree@*/
2694 }
2695 /*@=mustfree@*/
2696 else
2697 {
2698 uentry_setState (old, tthis);
2699 uentry_mergeState (old, fthis, loc, mustReturnF,
2700 TRUE, FALSE, cl);
2701 }
2702
2703 ttab->entries[tindex] = uentry_undefined;
2704 uentry_free (tthis);
2705 }
2706 else
2707 {
2708 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
2709 }
2710 }
2711
2712 for (i = 0; i < ttab->nentries; i++)
2713 {
2714 uentry current = ttab->entries[i];
2715
2716 if (!uentry_isUndefined (current))
2717 {
2718 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2719
2720 llassertprint (!uentry_isUndefined (old), ("name: <%s>",
2721 uentry_rawName (current)));
2722 if (mustReturnF)
2723 {
2724 uentry_mergeUses (current, old);
2725 uentry_setState (old, current);
2726 }
2727 else
2728 {
2729 /*
2730 ** assumes false branch is a fall-through if
2731 ** fbranch is not defined. This is true, unless
2732 ** where was some greivous error in processing
2733 ** the else branch of an if-then, in which case
2734 ** this is probably the right thing to do anyway.
2735 */
2736
2737 uentry_mergeState (old, current, loc, mustReturnT,
2738 FALSE, isOpt, cl);
2739 }
2740 }
2741 }
2742
2743
2744 /*
2745 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
2746 ** if they are present.
2747 */
2748
2749 llassert (NOALIAS (env->aliases, ttab->aliases));
2750 llassert (NOALIAS (env->aliases, ftab->aliases));
2751
2752 aliasTable_free (env->aliases);
2753
2754 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
2755 ftab->aliases, env->lexlevel);
2756
2757 aliasTable_fixSrefs (env->aliases);
2758
2759 /* exit true and false scopes */
2760 usymtab_quietPlainExitScope ();
2761 usymtab_quietPlainExitScope ();
2762
2763 if (mustReturnT)
2764 {
2765 utab->guards = guardSet_levelUnionFree
2766 (utab->guards,
2767 guardSet_invert (exprNode_getGuards (pred)),
2768 utab->lexlevel);
2769 }
2770
2771 if (mustReturnF)
2772 {
2773 utab->guards = guardSet_levelUnion (utab->guards,
2774 exprNode_getGuards (pred),
2775 utab->lexlevel);
2776 }
2777
2778 DPRINTF (("Here."));
2779}
2780
2781static void usymtab_fixCases (void) /*@modifies utab@*/ {
2782 while (utab->kind == US_CBRANCH)
2783 {
2784 usymtab_quietPlainExitScope ();
2785 }
2786
2787 llassert (utab->kind != US_CBRANCH);
2788}
2789
2790void
2791usymtab_altBranch (/*@only@*/ guardSet guards)
2792 /*@modifies utab@*/
2793{
2794 usymtab t = usymtab_create (US_FBRANCH, utab, FALSE);
2795 usymtab parent = utab->env;
2796
2797 /*
2798 ** If we are in a case, need to close it. The C syntax
2799 ** is very liberal, so this kludge is necessary.
2800 */
2801
2802 usymtab_fixCases ();
2803
2804 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
2805 llassert (utab->kind == US_TBRANCH);
2806 llassert (parent != GLOBAL_ENV);
2807
2808 guardSet_free (t->guards);
2809 t->guards = guards;
2810
2811 aliasTable_free (t->aliases);
2812 t->aliases = aliasTable_copy (parent->aliases);
2813
2814 utab = t;
2815}
2816
2817void
2818usymtab_allDefined (void)
2819 /*@globals utab, globtab@*/
2820{
2821 int i;
2822
2823 llassert (utab == globtab);
2824
2825 for (i = 0; i < utab->nentries; i++)
2826 {
2827 uentry e = utab->entries[i];
2828
2829 if (uentry_isPriv (e))
2830 {
2831 ; /* no need to define it */
2832 }
2833 else
2834 {
2835 if (context_getFlag (FLG_SPECUNDECL))
2836 {
2837 fileloc sloc = uentry_whereSpecified (e);
2838 fileloc dloc = uentry_whereDeclared (e);
2839
2840 if (fileloc_isDefined (sloc)
2841 && !uentry_isFakeTag (e)
2842 && !fileloc_isDefined (dloc))
2843 {
2844 voptgenerror
2845 (FLG_SPECUNDECL,
2846 message ("%s %q specified but not declared",
2847 ekind_capName (uentry_getKind (e)),
2848 uentry_getName (e)),
2849 sloc);
2850 }
2851 }
2852
2853 if (!uentry_isCodeDefined (e))
2854 {
2855 fileloc dloc = uentry_whereDeclared (e);
2856
2857 if (fileloc_isLib (dloc))
2858 {
2859 ;
2860 }
2861 else if (fileloc_isDefined (dloc))
2862 {
2863 if (!uentry_isAnyTag (e))
2864 {
2865 if (fileloc_isUser (dloc))
2866 {
2867 voptgenerror
2868 (FLG_DECLUNDEF,
2869 message ("%s %q declared but not defined",
2870 ekind_capName (uentry_getKind (e)),
2871 uentry_getName (e)),
2872 dloc);
2873 }
2874 }
2875 }
2876 else
2877 {
2878 fileloc sloc = uentry_whereSpecified (e);
2879
2880 if (fileloc_isDefined (sloc)
2881 && !fileloc_isImport (sloc)
2882 && !fileloc_isLib (sloc)
2883 && !fileloc_isPreproc (sloc)
2884 && !uentry_isFakeTag (e))
2885 {
2886 if (uentry_isVariable (e) || uentry_isFunction (e))
2887 {
2888 voptgenerror
2889 (FLG_SPECUNDEF,
2890 message ("%s %q specified but not declared or defined",
2891 ekind_capName (uentry_getKind (e)),
2892 uentry_getName (e)),
2893 sloc);
2894 }
2895 else
2896 {
2897 voptgenerror
2898 (FLG_SPECUNDEF,
2899 message ("%s %q specified but not defined",
2900 ekind_capName (uentry_getKind (e)),
2901 uentry_getName (e)),
2902 sloc);
2903 }
2904 }
2905 }
2906 }
2907 }
2908 }
2909}
2910
2911void usymtab_exportHeader (void)
2912 /*@globals utab@*/
2913{
2914 int i;
2915
2916 for (i = 0; i < utab->nentries; i++)
2917 {
2918 uentry ce = utab->entries[i];
2919
2920 if (!uentry_isDatatype (ce)
2921 && !uentry_isAnyTag (ce)
2922 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
2923 && !uentry_isExternal (ce)
2924 && !uentry_isForward (ce))
2925 {
2926 fileloc fwhere = uentry_whereDeclared (ce);
2927
2928 if (fileloc_isUndefined (fwhere)
2929 && uentry_isFunction (ce))
2930 {
2931 fwhere = uentry_whereDefined (ce);
2932 }
2933
2934 if (fileloc_isDefined (fwhere)
2935 && !fileloc_isHeader (fwhere)
2936 && !(fileloc_isSpecialFile (fwhere)
2937 && !context_getFlag (FLG_UNUSEDSPECIAL)))
2938 {
2939 if (uentry_isVariable (ce))
2940 {
2941 if (optgenerror
2942 (FLG_EXPORTHEADERVAR,
2943 message ("%s %q exported but not declared in header file",
2944 ekind_capName (uentry_getKind (ce)),
2945 uentry_getName (ce)),
2946 fwhere))
2947 {
2948 uentry_showDefSpecInfo (ce, fwhere);
2949 }
2950 }
2951 else
2952 {
2953 if (!uentry_isIter (ce)
2954 && !uentry_isEndIter (ce)
2955 && !uentry_isExpandedMacro (ce))
2956 {
2957 if (uentry_isFunction (ce)
2958 && cstring_equalLit (uentry_rawName (ce), "main"))
2959 {
2960 ; /* no error for main */
2961 }
2962 else
2963 {
2964 if (optgenerror
2965 (FLG_EXPORTHEADER,
2966 message ("%s %q exported but not declared "
2967 "in header file",
2968 ekind_capName (uentry_getKind (ce)),
2969 uentry_getName (ce)),
2970 fwhere))
2971 {
2972 uentry_showDefSpecInfo (ce, fwhere);
2973 }
2974 }
2975 }
2976 }
2977 }
2978 }
2979 }
2980}
2981
2982void usymtab_exportLocal (void)
2983 /*@globals utab@*/
2984{
2985 int i;
2986
2987
2988 for (i = 0; i < utab->nentries; i++)
2989 {
2990 uentry ce = utab->entries[i];
2991
2992
2993 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
2994 && !uentry_isEitherConstant (ce)
2995 && !uentry_isIter (ce)
2996 && !uentry_isEndIter (ce)
2997 && !uentry_isExpandedMacro (ce)
2998 && uentry_isUsed (ce))
2999 {
3000 /* check static uses */
3001 filelocList fuses = uentry_getUses (ce);
3002 fileloc mod = uentry_whereDefined (ce);
3003 bool ok = filelocList_isEmpty (fuses);
3004 fileloc fwhere = uentry_whereDeclared (ce);
3005
3006 if (fileloc_isSpecialFile (fwhere)
3007 && !context_getFlag (FLG_UNUSEDSPECIAL))
3008 {
3009 ok = TRUE; /* no errors for special files */
3010 }
3011 else
3012 {
3013 filelocList_elements (fuses, uloc)
3014 {
3015 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3016 {
3017 ok = TRUE;
3018 /*@innerbreak@*/ break;
3019 }
3020 } end_filelocList_elements;
3021 }
3022
3023 if (!ok)
3024 {
3025 if (optgenerror
3026 (FLG_EXPORTLOCAL,
3027 message ("%s exported but not used outside %s: %q",
3028 ekind_capName (uentry_getKind (ce)),
3029 fileloc_getBase (mod),
3030 uentry_getName (ce)),
3031 fwhere))
3032 {
3033 uentry_showDefSpecInfo (ce, fwhere);
3034 }
3035 }
3036 }
3037 }
3038}
3039
3040void
3041usymtab_allUsed (void)
3042 /*@globals utab@*/
3043{
3044 int i;
3045 bool isFileStatic = usymtab_inFileScope ();
3046 cstring last_file = cstring_undefined;
3047
3048 for (i = 0; i < utab->nentries; i++)
3049 {
3050 bool hasError = FALSE;
3051 uentry ce = utab->entries[i];
3052 fileloc fwhere = uentry_whereDeclared (ce);
3053
3054 if (fileloc_isUndefined (fwhere))
3055 {
3056 fwhere = uentry_whereDefined (ce);
3057 }
3058
3059 if (fileloc_isInvalid (fwhere)
3060 || fileloc_isLib (fwhere)
3061 || fileloc_isBuiltin (fwhere)
3062 || ((fileloc_isSpecialFile (fwhere)
3063 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3064 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3065 {
3066 ;
3067 }
3068 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3069 {
3070 cstring fname = fileloc_filename (fwhere);
3071
3072 if (cstring_isUndefined (last_file))
3073 {
3074 last_file = fname;
3075 }
3076 else if (cstring_equal (fname, last_file))
3077 {
3078 }
3079 else
3080 {
3081 cleanupMessages ();
3082 last_file = fname;
3083 }
3084
3085 if (uentry_isParam (ce))
3086 {
3087 if (context_inMacro ())
3088 {
3089 sRef cref = uentry_getSref (ce);
3090
3091 if (uentry_isYield (ce))
3092 {
3093 ; /* no checks (for now) */
3094 }
3095 else if (sRef_isSafe (cref))
3096 {
3097 ; /* no error */
3098 }
3099 else
3100 {
3101 if (uentry_hasRealName (ce))
3102 {
3103 hasError =
3104 optgenerror (FLG_MACROPARAMS,
3105 message ("Macro parameter %q not used",
3106 uentry_getName (ce)),
3107 fwhere);
3108 }
3109 }
3110 }
3111 else
3112 {
3113 if (cstring_equalFree (uentry_getName (ce),
3114 cstring_makeLiteral ("...")))
3115 {
3116 ;
3117 }
3118 else
3119 {
3120 hasError = optgenerror (FLG_PARAMUNUSED,
3121 message ("Parameter %q not used",
3122 uentry_getName (ce)),
3123 fwhere);
3124 }
3125 }
3126 } /* isParam */
3127 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3128 {
3129 if (fileloc_isUser (fwhere))
3130 {
3131 hasError = optgenerror
3132 (FLG_FUNCUNUSED,
3133 message ("%q %q declared but not used",
3134 cstring_makeLiteral
3135 (uentry_isIter (ce) ? "Iterator"
3136 : (isFileStatic ? "File static function" : "Function")),
3137 uentry_getName (ce)),
3138 fwhere);
3139 }
3140 }
3141 else if (uentry_isEndIter (ce))
3142 {
3143 ; /* no error (already reported for iter */
3144 }
3145 else if (uentry_isEnumConstant (ce))
3146 {
3147 if (fileloc_isUser (fwhere))
3148 {
3149 hasError = optgenerror
3150 (FLG_ENUMMEMUNUSED,
3151 message ("Enum member %q not used",
3152 uentry_getName (ce)),
3153 fwhere);
3154 }
3155 }
3156 else if (uentry_isConstant (ce))
3157 {
3158 if (fileloc_isUser (fwhere))
3159 {
3160 hasError = optgenerror
3161 (FLG_CONSTUNUSED,
3162 message ("Constant %q declared but not used",
3163 uentry_getName (ce)),
3164 fwhere);
3165 }
3166 }
3167 else if (uentry_isDatatype (ce))
3168 {
3169 if (fileloc_isUser (fwhere))
3170 {
3171 hasError = optgenerror
3172 (FLG_TYPEUNUSED,
3173 message ("Type %q declared but not used",
3174 uentry_getName (ce)),
3175 fwhere);
3176 }
3177 }
3178 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3179 { /* errors for ref params will be reported in the next scope */
3180 llassertprint (uentry_isVar (ce),
3181 ("ce: %s", uentry_unparseFull (ce)));
3182
3183 if (ctype_isFunction (uentry_getType (ce)))
3184 {
3185 if (fileloc_isUser (fwhere))
3186 {
3187 hasError = optgenerror
3188 (FLG_FUNCUNUSED,
3189 message ("%q %q declared but not used",
3190 cstring_makeLiteral
3191 (isFileStatic ? "File static function"
3192 : "Function"),
3193 uentry_getName (ce)),
3194 fwhere);
3195 }
3196 }
3197 else
3198 {
3199 if (fileloc_isUser (fwhere))
3200 {
3201
3202
3203 hasError = optgenerror
3204 (FLG_VARUNUSED,
3205 message ("%q %q declared but not used",
3206 cstring_makeLiteral
3207 (isFileStatic ? "File static variable"
3208 : "Variable"),
3209 uentry_getName (ce)),
3210 fwhere);
3211 }
3212 }
3213 }
3214 else
3215 {
3216 ; /* no errors */
3217 }
3218 } /* unused */
3219 else if (uentry_isDatatype (ce) || uentry_isAnyTag (ce))
3220 { /* check all fields */
3221 ctype ct = uentry_getRealType (ce);
3222
3223
3224 while (ctype_isAP (ct))
3225 {
3226 ct = ctype_getBaseType (ct);
3227 }
3228
3229
3230 if (ctype_isSU (ct))
3231 {
3232 uentryList fields = ctype_getFields (ct);
3233
3234 uentryList_elements (fields, field)
3235 {
3236 if (!uentry_isUsed (field))
3237 {
3238 if (uentry_hasName (ce))
3239 {
3240 hasError |= optgenerror
3241 (FLG_FIELDUNUSED,
3242 message ("Field %q of %s %q declared but not used",
3243 uentry_getName (field),
3244 cstring_makeLiteralTemp
3245 (ctype_isStruct (ct) ? "structure" : "union"),
3246 uentry_getName (ce)),
3247 uentry_whereEarliest (field));
3248 }
3249 else
3250 {
3251 hasError |= optgenerror
3252 (FLG_FIELDUNUSED,
3253 message ("Field %q of unnamed %s declared but not used",
3254 uentry_getName (field),
3255 cstring_makeLiteralTemp
3256 (ctype_isStruct (ct) ? "structure" : "union")),
3257 uentry_whereEarliest (field));
3258 }
3259
3260 uentry_setUsed (field, fileloc_undefined);
3261 }
3262 } end_uentryList_elements;
3263 }
3264 }
3265 else
3266 {
3267 ; /* no errors */
3268 }
3269
3270 if (hasError)
3271 {
3272 if (uentry_isParam (ce) && context_inMacro ())
3273 {
3274 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3275 {
3276 uentry_showWhereSpecified (ce);
3277 }
3278 }
3279 else
3280 {
3281 uentry_showDefSpecInfo (ce, fwhere);
3282 }
3283
3284 uentry_setUsed (ce, fileloc_undefined);
3285 }
3286 }
3287}
3288
3289static void
3290checkGlobalReturn (uentry glob, sRef orig)
3291{
3292 sRef sr = uentry_getSref (glob);
3293
3294
3295 if (context_getFlag (FLG_GLOBSTATE))
3296 {
3297 if (sRef_isKilledGlob (orig))
3298 {
3299 if (sRef_isStateUndefined (sr)
3300 || sRef_isUnuseable (sr)
3301 || sRef_isStateUnknown (sr)
3302 || sRef_isDead (sr))
3303 {
3304 ;
3305 }
3306 else
3307 {
3308 ctype ct = ctype_realType (uentry_getType (glob));
3309
3310 if (ctype_isVisiblySharable (ct))
3311 {
3312 if (optgenerror
3313 (FLG_GLOBSTATE,
3314 message
3315 ("Killed global %q not released before return",
3316 uentry_getName (glob)),
3317 g_currentloc))
3318 {
3319 sRef_showStateInfo (sr);
3320 }
3321 }
3322 else
3323 {
3324 sRef_protectDerivs ();
3325 (void) checkGlobalDestroyed (sr, g_currentloc);
3326 sRef_clearProtectDerivs ();
3327 }
3328 }
3329 }
3330 else
3331 {
3332 if (sRef_isStateUndefined (sr))
3333 {
3334 if (optgenerror (FLG_GLOBSTATE,
3335 message
3336 ("Function returns with global %q undefined",
3337 uentry_getName (glob)),
3338 g_currentloc))
3339 {
3340 sRef_showStateInfo (sr);
3341 }
3342 }
3343 else
3344 {
3345 if (sRef_isDead (sr))
3346 {
3347 if (optgenerror
3348 (FLG_GLOBSTATE,
3349 message ("Function returns with global %q "
3350 "referencing released storage",
3351 uentry_getName (glob)),
3352 g_currentloc))
3353 {
3354 sRef_showStateInfo (sr);
3355 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3356 }
3357 }
3358
3359 if (ctype_isRealPointer (uentry_getType (glob)) &&
3360 sRef_possiblyNull (sr) && !uentry_possiblyNull (glob))
3361 {
3362 if (optgenerror
3363 (FLG_GLOBSTATE,
3364 message ("Function returns with non-null global %q "
3365 "referencing null storage",
3366 uentry_getName (glob)),
3367 g_currentloc))
3368 {
3369 sRef_showNullInfo (sr);
3370 }
3371 }
3372 else
3373 {
3374 checkGlobReturn (glob);
3375 }
3376 }
3377 }
3378 }
3379}
3380
3381/*
3382** remember: check alias globals
3383*/
3384
3385void usymtab_checkFinalScope (bool isReturn)
3386 /*@globals utab@*/
3387{
3388 bool mustFree = context_getFlag (FLG_MUSTFREE);
3389 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3390 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3391 sRefSet checked = sRefSet_new ();
3392 usymtab stab = utab;
3393 int i;
3394
3395 /*
3396 ** need to check all scopes out to function parameters.
3397 */
3398
3399 do
3400 {
3401 for (i = 0; i < stab->nentries; i++)
3402 {
3403 uentry ce = stab->entries[i];
3404 sRef sr = uentry_getSref (ce);
3405 sRef rb = sRef_getRootBase (sr);
3406
3407 if (ctype_isFunction (uentry_getType (ce)))
3408 {
3409 /*@innercontinue@*/ continue;
3410 }
3411
3412 if (mustFree)
3413 {
3414 DPRINTF (("Check entry: %s", uentry_unparseFull (ce)));
3415
3416 if (!sRefSet_member (checked, sr) && !sRef_isGlobal (rb))
3417 {
3418 if (ctype_isRealSU (uentry_getType (ce))
3419 && !uentry_isAnyParam (ce)
3420 && !uentry_isRefParam (ce)
3421 && !uentry_isStatic (ce)
3422 && !sRef_isDependent (sr)
3423 && !sRef_isOwned (sr))
3424 {
3425 sRefSet als = usymtab_allAliases (sr);
3426
3427
3428 if (sRefSet_isEmpty (als))
3429 {
3430 checkLocalDestroyed (sr, g_currentloc);
3431 }
3432 else
3433 {
3434 /* aliased, no problem */ ;
3435 }
3436
3437 sRefSet_free (als);
3438 }
3439 else if
3440 (!uentry_isStatic (ce)
3441 && ((sRef_isNewRef (sr))
3442 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3443 || sRef_isKeep (sr) || sRef_isOwned (sr))
3444 && !sRef_isDead (sr))
3445 && (!sRef_definitelyNull (sr))
3446 && (!usymtab_isProbableNull (sr)))))
3447 {
3448 bool hasError = TRUE;
3449
3450 /*
3451 ** If its a scope exit, check if there is an alias.
3452 ** If so, make it only. If not, there is an error.
3453 */
3454
3455 if (!isReturn)
3456 {
3457 if (canLoseReference (sr, g_currentloc))
3458 {
3459 hasError = FALSE;
3460 }
3461 }
3462
3463 if (hasError)
3464 {
3465 if (sRef_hasLastReference (sr))
3466 {
3467 sRef ar = sRef_getAliasInfoRef (sr);
3468
3469 if (optgenerror
3470 (FLG_MUSTFREE,
3471 message
3472 ("Last reference %q to %s storage %qnot %q before %q",
3473 sRef_unparse (sr),
3474 alkind_unparse (sRef_getAliasKind (sr)),
3475 sRef_unparseOpt (ar),
3476 cstring_makeLiteral (sRef_isKeep (sr)
3477 ? "transferred" : "released"),
3478 cstring_makeLiteral (isReturn
3479 ? "return" : "scope exit")),
3480 g_currentloc))
3481 {
3482 sRef_showRefLost (sr);
3483 }
3484 }
3485 else if (sRef_isNewRef (sr))
3486 {
3487 if (optgenerror
3488 (FLG_MUSTFREE,
3489 message
3490 ("%q %q not released before %q",
3491 cstring_makeLiteral
3492 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
3493 ? "Kill reference parameter" : "New reference"),
3494 uentry_getName (ce),
3495 cstring_makeLiteral (isReturn
3496 ? "return" : "scope exit")),
3497 g_currentloc))
3498 {
3499 sRef_showAliasInfo (sr);
3500 }
3501 }
3502 else
3503 {
3504 if (ctype_isRealSU (sRef_getType (sr)))
3505 {
3506 checkStructDestroyed (sr, g_currentloc);
3507 }
3508 else
3509 {
3510 if (optgenerror
3511 (FLG_MUSTFREE,
3512 message
3513 ("%s storage %q not %q before %q",
3514 alkind_capName (sRef_getAliasKind (sr)),
3515 uentry_getName (ce),
3516 cstring_makeLiteral (sRef_isKeep (sr)
3517 ? "transferred" : "released"),
3518 cstring_makeLiteral (isReturn
3519 ? "return" : "scope exit")),
3520 g_currentloc))
3521 {
3522 sRef_showAliasInfo (sr);
3523 }
3524 }
3525 }
3526 }
3527 }
3528 else
3529 {
3530 ;
3531 }
3532 }
3533 else if (mustDefine && uentry_isOut (ce))
3534 {
3535 if (!ynm_toBoolStrict (sRef_isReadable (sr)))
3536 {
3537 voptgenerror
3538 (FLG_MUSTDEFINE,
3539 message ("Out storage %q not defined before %q",
3540 uentry_getName (ce),
3541 cstring_makeLiteral
3542 (isReturn ? "return" : "scope exit")),
3543 g_currentloc);
3544
3545 /* uentry_showWhereDeclared (ce); */
3546 }
3547 }
3548 else
3549 {
3550 ;
3551 }
3552
3553 /*
3554 ** also check state is okay
3555 */
3556
3557 if (usymtab_lexicalLevel () > functionScope
3558 && uentry_isVariable (ce)
3559 && (sRef_isLocalVar (sr)
3560 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
3561 {
3562 sRefSet ab = usymtab_aliasedBy (sr);
3563
3564 /* should do something more efficient here */
3565
3566 if (sRefSet_isEmpty (ab))
3567 {
3568 /* and no local ref */
3569 checkLoseRef (ce);
3570 }
3571 else
3572 {
3573 ;
3574 }
3575
3576 sRefSet_free (ab);
3577 }
3578 else
3579 {
3580 ;
3581 }
3582
3583 checked = sRefSet_insert (checked, sr);
3584 }
3585 }
3586 llassert (usymtab_isDefined (stab->env));
3587
3588 if (usymtab_isBranch (stab))
3589 {
3590 stab = usymtab_dropEnv (stab);
3591 }
3592 else
3593 {
3594 stab = stab->env;
3595 }
3596
3597 llassert (stab != usymtab_undefined);
3598 } while (isReturn && (stab->lexlevel >= paramsScope));
3599
3600 sRefSet_free (checked);
3601
3602 /*
3603 ** for returns:
3604 ** all globals are appropriately defined
3605 ** all parameters are appropriately defined
3606 ** special clauses are followed
3607 */
3608
3609 if (isReturn || (utab->lexlevel == paramsScope))
3610 {
3611 uentry fcn = context_getHeader ();
3612 uentryList params = context_getParams ();
3613 globSet uglobs = context_getUsedGlobs ();
3614 globSet sglobs = context_getGlobs ();
3615
3616
3617 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
3618 {
3619 aliasTable_checkGlobs (utab->aliases);
3620 }
3621
3622 /*
3623 ** special clauses (defines, sets, allocates, releases)
3624 */
3625
3626 if (uentry_hasSpecialClauses (fcn))
3627 {
3628 specialClauses clauses = uentry_getSpecialClauses (fcn);
3629
3630 specialClauses_elements (clauses, cl)
3631 {
3632 if (specialClause_isAfter (cl))
3633 { /* evs - 2000 07 10 - added this */
3634 sRefTest tst = specialClause_getPostTestFunction (cl);
3635 sRefSet rfs = specialClause_getRefs (cl);
3636
3637 sRefSet_elements (rfs, el)
3638 {
3639 sRef base = sRef_getRootBase (el);
3640
3641 if (sRef_isResult (base))
3642 {
3643 ;
3644 }
3645 else if (sRef_isParam (base))
3646 {
3647 sRef sr = sRef_updateSref (base);
3648 sr = sRef_fixBase (el, sr);
3649
3650 if (tst != NULL && !tst (sr))
3651 {
3652 if (optgenerror
3653 (specialClause_postErrorCode (cl),
3654 message ("%s storage %qcorresponds to "
3655 "storage listed in %q clause",
3656 specialClause_postErrorString (cl, sr),
3657 sRef_unparseOpt (sr),
3658 specialClause_unparseKind (cl)),
3659 g_currentloc))
3660 {
3661 sRefShower ss = specialClause_getPostTestShower (cl);
3662
3663 if (ss != NULL)
3664 {
3665 ss (sr);
3666 }
3667 }
3668 }
3669 }
3670 else
3671 {
3672 if (sRef_isMeaningful (el))
3673 {
3674 BADBRANCH;
3675 }
3676 }
3677 } end_sRefSet_elements ;
3678 }
3679 } end_specialClauses_elements ;
3680 }
3681
3682 /*
3683 ** check parameters on return
3684 */
3685
3686 uentryList_elements (params, arg)
3687 {
3688 if (!uentry_isElipsisMarker (arg))
3689 {
3690 ctype rt = ctype_realType (uentry_getType (arg));
3691
3692 if (ctype_isMutable (rt) || ctype_isSU (rt))
3693 {
3694 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
3695 checkParamReturn (param);
3696 }
3697 }
3698 } end_uentryList_elements;
3699
3700 globSet_allElements (sglobs, el)
3701 {
3702 uentry current = sRef_getUentry (el);
3703
3704 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
3705 {
3706 checkGlobalReturn (current, el);
3707 }
3708 } end_globSet_allElements;
3709
3710 globSet_allElements (uglobs, el)
3711 {
3712 if (!globSet_member (sglobs, el))
3713 {
3714 uentry current = sRef_getUentry (el);
3715
3716
3717 if (uentry_isVariable (current)
3718 && !uentry_isRealFunction (current))
3719 {
3720 checkGlobalReturn (current, sRef_undefined);
3721 }
3722 }
3723 } end_globSet_allElements;
3724 }
3725
3726 }
3727
3728void
3729usymtab_quietExitScope (fileloc loc)
3730 /*@globals utab, globtab, filetab; @*/
3731 /*@modifies utab@*/
3732{
3733 usymtab t = utab->env;
3734
3735 if (utab->reftable != NULL)
3736 {
3737 int i;
3738
3739 for (i = 0; i < utab->nentries; i++)
3740 {
3741 uentry current = utab->entries[i];
3742 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
3743
3744 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
3745 }
3746 }
3747
3748 llassert (t != NULL);
3749
3750 if (t->lexlevel > paramsScope)
3751 {
3752 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
3753 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
3754 t->lexlevel);
3755 utab->aliases = aliasTable_undefined;
3756 }
3757
3758 t->mustBreak = utab->mustBreak;
3759 t->exitCode = utab->exitCode;
3760
3761 usymtab_freeLevel (utab);
3762
3763 utab = t;
3764}
3765
3766/*
3767** Exit a scope with no checking, lose alias states.
3768** (When should this be used?)
3769*/
3770
3771void usymtab_quietPlainExitScope (void)
3772 /*@globals utab, globtab, filetab@*/
3773 /*@modifies utab@*/
3774{
3775 usymtab t = utab->env;
3776
3777 llassert (t != NULL);
3778 llassert (NOALIAS (utab->aliases, t->aliases));
3779 usymtab_freeLevel (utab);
3780 utab = t;
3781}
3782
3783void usymtab_exitScope (exprNode expr)
3784 /*@globals utab, filetab, globtab@*/
3785 /*@modifies utab, globtab@*/
3786{
3787 usymtab ctab = usymtab_undefined;
3788 usymtab lctab = usymtab_undefined;
3789 bool mustReturn = exprNode_mustEscape (expr);
3790
3791 if (utab->kind == US_CBRANCH)
3792 {
3793 /*
3794 ** save the case branches, remove the first non-cbranch
3795 */
3796
3797 ctab = utab;
3798
3799 while (utab->kind == US_CBRANCH)
3800 {
3801 lctab = utab;
3802 utab = utab->env;
3803 llassert (utab != GLOBAL_ENV);
3804 }
3805 }
3806
3807 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
3808 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH) {
3809
3810 if (context_inMacro ()) {
3811 /* evs 2000-07-25 */
3812 /* Unparseable macro may end inside nested scope. Deal with it. */
3813
3814 llerror (FLG_SYNTAX, message ("Problem parsing macro body of %s (unbalanced scopes). Attempting to recover, recommend /*@notfunction@*/ before macro definition.",
3815 context_inFunctionName ()));
3816
3817 while (utab->kind == US_TBRANCH
3818 || utab->kind == US_FBRANCH
3819 || utab->kind == US_CBRANCH
3820 || utab->kind == US_SWITCH)
3821 {
3822 utab = utab->env;
3823 llassert (utab != GLOBAL_ENV);
3824 }
3825 } else {
2934b455 3826 llcontbug (message ("exitScope: in branch: %s", usymtab_unparseStack ()));
616915dd 3827 /*@-branchstate@*/
3828 } /*@=branchstate@*/
3829 }
3830
3831 /*
3832 ** check all variables in scope were used
3833 */
3834
3835 /*
3836 ** bogus errors if this is the normal inside a switch,
3837 ** since cases have not been merged yet. Should probably
3838 ** still check this, but I'm too lazy at the moment...
3839 */
3840
3841 llassertfatal (utab->env != GLOBAL_ENV);
3842
3843 if (utab->env->kind != US_SWITCH)
3844 {
3845 usymtab_allUsed ();
3846 }
3847
3848 /*
3849 ** check aliasing: all only params are released (dead)
3850 ** definition: all out params are defined, all modified params
3851 ** are completely defined
3852 **
3853 ** NOTE: note for exiting paramsScope, since checkReturn should be
3854 ** called first.
3855 */
3856
3857 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
3858 {
3859 /*
3860 ** should only call this is end of scope is reachable...
3861 */
3862
3863 usymtab_checkFinalScope (FALSE);
3864 }
3865
3866 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
3867 {
3868 /*
3869 ** leaving a function, need to fix up globals
3870 */
3871
3872 uentryList params = context_getParams ();
3873 globSet globs = context_getUsedGlobs ();
3874
3875
3876 uentryList_elements (params, ue)
3877 {
3878 uentry_fixupSref (ue);
3879 } end_uentryList_elements;
3880
3881 clearFunctionTypes ();
3882
3883
3884 globSet_allElements (globs, el)
3885 {
3886 if (sRef_isCvar (el))
3887 {
3888 uentry current;
3889 int index = sRef_getScopeIndex (el);
3890
3891 if (sRef_isFileStatic (el))
3892 {
3893 llassert (usymtab_isDefined (filetab));
3894 current = usymtab_fetchIndex (filetab, index);
3895 }
3896 else
3897 {
3898 current = usymtab_fetchIndex (globtab, index);
3899 }
3900
3901 if (uentry_isVariable (current))
3902 {
3903 uentry_fixupSref (current);
3904 }
3905 else
3906 {
3907 sRef_clearDerived (uentry_getSref (current));
3908 }
3909 }
3910 } end_globSet_allElements;
3911 }
3912
3913 usymtab_quietExitScope (exprNode_loc (expr));
3914
3915 if (lctab != usymtab_undefined)
3916 {
3917 /*@i@*/ lctab->env = utab;
3918 /*@i@*/ utab = ctab;
3919 /*@-branchstate@*/ } /*@=branchstate@*/
3920/*@-globstate@*/
3921}
3922/*@=globstate@*/
3923
3924/*
3925** yikes! don't let the '170 kids see this one...
3926*/
3927
3928int
3929uentry_directParamNo (uentry ue)
3930{
3931 if (uentry_isVar (ue))
3932 {
3933 sRef sr = uentry_getSref (ue);
3934
3935 if (sRef_lexLevel (sr) == functionScope)
3936 {
3937 /*@access sRef@*/ /*@-null@*/
3938 int index = sr->info->cvar->index;
3939 /*@noaccess sRef@*/ /*@=null@*/
3940
3941 if (index < uentryList_size (context_getParams ()))
3942 {
3943 return index;
3944 }
3945 }
3946 }
3947 return -1;
3948}
3949
3950/*@dependent@*/ /*@exposed@*/ uentry
3951 usymtab_getParam (int paramno)
3952 /*@globals utab@*/
3953{
3954 /*
3955 ** requires in a function context (checked)
3956 **
3957 ** depends on no nested functions --- the function
3958 ** parameters are ALWAYS one scope inside the global scope
3959 ** and entered in order!
3960 */
3961 usymtab s = utab;
3962
3963 if (!context_inFunctionLike ())
3964 llfatalbug (message ("usymtab_getParam: not in function context: %q",
3965 context_unparse ()));
3966
3967 while (s->lexlevel > paramsScope)
3968 {
3969 s = s->env;
3970 }
3971
3972 llassert (usymtab_isDefined (s));
3973
3974 if (paramno >= s->nentries)
3975 {
3976 /*
3977 ** Parse errors lead to this.
3978 */
3979
3980 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
3981 ctype_unknown);
3982
3983 uentry_markOwned (err);
3984 return (err);
3985 }
3986
3987 return (s->entries[paramno]);
3988}
3989
3990static /*@dependent@*/ /*@exposed@*/ uentry
3991usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
3992{
3993 uentry ue;
3994
3995
3996 ue = usymtab_getRefNoisy (u, level, index);
3997
3998
3999 if (uentry_isUndefined (ue))
4000 {
4001 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4002 index, level));
4003 }
4004
4005
4006 return ue;
4007}
4008
4009static /*@dependent@*/ /*@exposed@*/ usymtab
4010 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4011{
4012 if (s->kind == US_CBRANCH)
4013 {
4014 usymtab t = s;
4015
4016 do
4017 {
4018 t = s;
4019 s = s->env;
4020 llassert (s != GLOBAL_ENV);
4021 } while (s->kind == US_CBRANCH);
4022 /* drop all cases (except in nested scopes */
4023
4024 s = t;
4025 llassert (s != GLOBAL_ENV);
4026 }
4027
4028 if (s->kind == US_FBRANCH)
4029 {
4030 s = s->env; /* skip the true branch */
4031 llassert (usymtab_isDefined (s));
4032 llassert (s->kind == US_TBRANCH);
4033 }
4034
4035 llassert (s != GLOBAL_ENV);
4036 s = s->env;
4037
4038 return s;
4039}
4040
4041/*@dependent@*/ /*@exposed@*/ uentry
4042 usymtab_getRefQuiet (int level, usymId index)
4043 /*@globals utab@*/
4044{
4045 usymtab s = utab;
4046
4047
4048 llassert (s != NULL);
4049 llassert (index >= 0);
4050
4051 if (level > s->lexlevel)
4052 {
4053
4054 return uentry_undefined;
4055 }
4056
4057 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4058 level, s->lexlevel));
4059
4060 while (s->lexlevel > level)
4061 {
4062 if (usymtab_isBranch (s))
4063 {
4064 int eindex = refTable_lookup (s, level, index);
4065
4066 if (eindex != NOT_FOUND)
4067 {
4068 return (s->entries[eindex]);
4069 }
4070 }
4071
4072 s = usymtab_dropEnv (s);
4073 }
4074
4075 while (usymtab_isBranch (s) && s->lexlevel == level)
4076 {
4077 int eindex = refTable_lookup (s, level, index);
4078
4079 if (eindex != NOT_FOUND)
4080 {
4081 return (s->entries[eindex]);
4082 }
4083
4084 s = usymtab_dropEnv (s);
4085 }
4086
4087 if (index >= s->nentries)
4088 {
4089 return uentry_undefined;
4090 }
4091
4092 llassert (!uentry_isUndefined (s->entries[index]));
4093
4094 return s->entries[index];
4095}
4096
4097static /*@dependent@*/ /*@exposed@*/ uentry
4098usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4099{
4100 usymtab otab = s;
4101 uentry ue = uentry_undefined;
4102
4103
4104 llassert (index >= 0);
4105
4106
4107 while (s->lexlevel > level)
4108 {
4109
4110 if (usymtab_isBranch (s))
4111 {
4112 int eindex = refTable_lookup (s, level, index);
4113
4114 if (eindex != NOT_FOUND)
4115 {
4116 ue = s->entries[eindex];
4117
4118 if (s != otab)
4119 {
4120 while (!usymtab_isBranch (otab))
4121 {
4122 otab = usymtab_dropEnv (otab);
4123 llassert (otab != GLOBAL_ENV);
4124 }
4125
4126 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4127 {
4128 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4129 }
4130 else
4131 {
4132 ;
4133 }
4134 }
4135
4136 return ue;
4137 }
4138 }
4139
4140 s = usymtab_dropEnv (s);
4141 }
4142
4143 llassert (usymtab_isDefined (s));
4144
4145 while (usymtab_isBranch (s) && s->lexlevel == level)
4146 {
4147 int eindex = refTable_lookup (s, level, index);
4148
4149
4150 if (eindex != NOT_FOUND)
4151 {
4152 ue = s->entries[eindex];
4153
4154 if (s != otab)
4155 {
4156 while (!usymtab_isBranch (otab))
4157 {
4158 otab = usymtab_dropEnv (otab);
4159 llassert (otab != GLOBAL_ENV);
4160 }
4161
4162 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4163 }
4164 else
4165 {
4166 ;
4167 }
4168
4169 return ue;
4170 }
4171
4172 s = usymtab_dropEnv (s);
4173 }
4174
4175 if (s->lexlevel == level && (index < s->nentries))
4176 {
4177 ue = s->entries[index];
4178
4179 if (uentry_isValid (ue))
4180 {
4181 if (s != otab)
4182 {
4183 while (!usymtab_isBranch (otab))
4184 {
4185 otab = usymtab_dropEnv (otab);
4186
4187 if (otab == GLOBAL_ENV)
4188 {
4189 return ue;
4190 }
4191 }
4192
4193 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4194 }
4195 else
4196 {
4197 }
4198 }
4199
4200 return ue;
4201 }
4202
4203
4204 if (index >= s->nentries)
4205 {
4206 return uentry_undefined;
4207 }
4208
4209 llassert (!uentry_isUndefined (s->entries[index]));
4210
4211 return s->entries[index];
4212}
4213
4214/*
4215** looking up entries
4216**
4217** If entry is inside a branch, then copy it, and put it into
4218** the branch table.
4219*/
4220
4221static
4222int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4223{
4224 refTable rt = ut->reftable;
4225 int i;
4226
4227 llassert (rt != NULL);
4228
4229
4230 for (i = 0; i < ut->nentries; i++)
4231 {
4232 if (rt[i]->level == level && rt[i]->index == index)
4233 {
4234 return i;
4235 }
4236 }
4237
4238 return NOT_FOUND;
4239}
4240
4241static
4242/*@only@*/ refentry refentry_create (int level, int index)
4243{
4244 refentry r = (refentry) dmalloc (sizeof (*r));
4245
4246 r->level = level;
4247 r->index = index;
4248
4249 return r;
4250}
4251
4252static /*@dependent@*/ /*@exposed@*/ uentry
4253usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4254{
4255 int eindex;
4256 usymtab ut = s;
4257
4258 llassert (ut->reftable != NULL);
4259
4260 while (s != GLOBAL_ENV)
4261 {
4262 eindex = usymtab_getIndex (s, k);
4263
4264 if (eindex != NOT_FOUND)
4265 {
4266 uentry current = s->entries[eindex];
4267
4268 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4269 {
4270 uentry ue;
4271
4272 DPRINTF (("Here: copying %s", uentry_unparseFull (current)));
4273
4274 ue = uentry_copy (current);
4275
4276 DPRINTF (("Here: copying %s", uentry_unparseFull (ue)));
4277
4278 usymtab_addEntryQuiet (ut, ue);
4279
4280 if (s->reftable != NULL)
4281 {
4282 refentry ref = s->reftable[eindex];
4283
4284
4285 ut->reftable[ut->nentries - 1]
4286 = refentry_create (ref->level, ref->index);
4287 }
4288 else
4289 {
4290 ut->reftable[ut->nentries - 1]
4291 = refentry_create (s->lexlevel, eindex);
4292 }
4293
4294 return (ue);
4295 }
4296 else
4297 {
4298 return (current);
4299 }
4300 }
4301
4302 s = usymtab_dropEnv (s);
4303 }
4304
4305 return uentry_undefined;
4306}
4307
4308static uentry usymtab_lookupAux (usymtab s, cstring k)
4309{
4310 DPRINTF (("Lookup: %s", k));
4311
4312 while (s != GLOBAL_ENV)
4313 {
4314 int eindex = usymtab_getIndex (s, k);
4315
4316 if (eindex != NOT_FOUND)
4317 {
4318 uentry ret = s->entries[eindex];
4319
4320 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4321 return (ret);
4322 }
4323
4324 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4325 || s->kind == US_CBRANCH)
4326 {
4327 uentry ret = usymtab_addRefEntry (s, k);
4328 DPRINTF (("Ref entry: %s", uentry_unparseFull (ret)));
4329 return ret;
4330 }
4331
4332 s = s->env;
4333 }
4334
4335 return uentry_undefined;
4336}
4337
4338static /*@dependent@*/ /*@exposed@*/ uentry
4339usymtab_lookupQuiet (usymtab s, cstring k)
4340{
4341 int eindex;
4342
4343 while (s != GLOBAL_ENV)
4344 {
4345 eindex = usymtab_getIndex (s, k);
4346
4347 if (eindex != NOT_FOUND)
4348 {
4349 uentry ret = s->entries[eindex];
4350 return (ret);
4351 }
4352
4353 s = s->env;
4354 }
4355
4356 return uentry_undefined;
4357}
4358
4359/*@dependent@*/ /*@observer@*/ uentry
4360 usymtab_lookupSafe (cstring k)
4361 /*@globals utab@*/
4362{
4363 DPRINTF (("Lookup safe: %s", k));
4364 return (usymtab_lookupAux (utab, k));
4365}
4366
4367uentry
4368 usymtab_lookupExpose (cstring k)
4369 /*@globals utab@*/
4370{
4371 uentry ce = usymtab_lookupAux (utab, k);
4372
4373 if (uentry_isUndefined (ce))
4374 {
4375 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
4376 }
4377
4378 if (uentry_isPriv (ce))
4379 {
4380 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
4381 }
4382
4383 return ce;
4384}
4385
4386uentry usymtab_lookupExposeGlob (cstring k)
4387{
4388 return (usymtab_lookupGlobSafe (k));
4389}
4390
4391uentry usymtab_lookupGlob (cstring k)
4392 /*@globals globtab@*/
4393{
4394 uentry ce = usymtab_lookupAux (globtab, k);
4395
4396 if (uentry_isUndefined (ce))
4397 llfatalbug (message ("usymtab_lookup: not found: %s", k));
4398
4399 if (uentry_isPriv (ce))
4400 llfatalbug (message ("usymtab_lookup: private: %s", k));
4401
4402 return ce;
4403}
4404
4405/*@observer@*/ uentry
4406 usymtab_lookupGlobSafe (cstring k)
4407 /*@globals globtab@*/
4408{
4409 uentry ce = usymtab_lookupAux (globtab, k);
4410
4411 return ce;
4412}
4413
4414uentry usymtab_lookupEither (cstring k)
4415 /*@globals utab@*/
4416{
4417 uentry ce = usymtab_lookupSafe (k);
4418
4419 if (uentry_isUndefined (ce))
4420 llfatalerror (message ("usymtab_lookup: not found: %s", k));
4421
4422 return ce;
4423}
4424
4425# ifndef NOLCL
4426ctype
4427usymtab_lookupType (cstring k)
4428 /*@globals globtab@*/
4429{
4430 usymId uid = usymtab_getTypeId (k);
4431
4432 if (uid == USYMIDINVALID)
4433 {
4434 llcontbug (message ("usymtab_lookupType: not found: %s", k));
4435 return ctype_unknown;
4436 }
4437
4438 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
4439}
4440# endif
4441
4442ctype
4443usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
4444{
4445 usymId uid = usymtab_getTypeId (k);
4446
4447 if (uid == USYMIDINVALID)
4448 {
4449 llcontbug (message ("usymtab_lookupType: not found: %s", k));
4450 return ctype_unknown;
4451 }
4452
4453 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
4454}
4455
4456/*
4457** if there is an unnamed lcl-specified struct tag matching
4458** the uentryList, return its datatype. Otherwise, returns
4459** ctype_undefined.
4460*/
4461
4462ctype
4463usymtab_structFieldsType (uentryList f)
4464 /*@globals globtab@*/
4465{
4466 return (usymtab_suFieldsType (f, TRUE));
4467}
4468
4469ctype
4470usymtab_unionFieldsType (uentryList f)
4471 /*@globals globtab@*/
4472{
4473 return (usymtab_suFieldsType (f, FALSE));
4474}
4475
4476static ctype
4477usymtab_suFieldsType (uentryList f, bool isStruct)
4478 /*@globals globtab@*/
4479{
4480 int i;
4481
4482 if (fileloc_isSpec (g_currentloc)) return (ctype_undefined);
4483
4484 for (i = 0; i < globtab->nentries; i++)
4485 {
4486 uentry current = globtab->entries[i];
4487
4488 if ((isStruct
4489 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
4490 {
4491 if (isFakeTag (uentry_rawName (current)))
4492 {
4493 ctype ct = uentry_getType (current);
4494
4495 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
4496 && (uentryList_matchFields (f, ctype_getFields (ct))))
4497 {
4498 return uentry_getAbstractType (current);
4499 }
4500 }
4501 }
4502 }
4503
4504 return ctype_undefined;
4505}
4506
4507ctype
4508 usymtab_enumEnumNameListType (enumNameList f)
4509 /*@globals globtab@*/
4510{
4511 int i;
4512
4513 for (i = 0; i < globtab->nentries; i++)
4514 {
4515 uentry current = globtab->entries[i];
4516
4517 if (uentry_isEnumTag (current))
4518 {
4519 if (isFakeTag (uentry_rawName (current)))
4520 {
4521 ctype ct = uentry_getType (current);
4522
4523 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
4524 {
4525 return uentry_getType (current);
4526 }
4527 }
4528 }
4529 }
4530
4531 return ctype_undefined;
4532}
4533
4534bool
4535usymtab_exists (cstring k)
4536 /*@globals utab@*/
4537{
4538 uentry ce = usymtab_lookupSafe (k);
4539
4540 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4541}
4542
4543bool
4544usymtab_existsReal (cstring k)
4545 /*@globals utab@*/
4546{
4547 uentry ce = usymtab_lookupSafe (k);
4548
4549 return (!(uentry_isUndefined (ce))
4550 && !(uentry_isPriv (ce))
4551 && !(uentry_isExpandedMacro (ce)));
4552}
4553
4554bool
4555 usymtab_existsGlob (cstring k)
4556 /*@globals globtab@*/
4557{
4558 uentry ce = usymtab_lookupAux (globtab, k);
4559
4560 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4561}
4562
4563# ifndef NOLCL
4564bool
4565usymtab_existsEither (cstring k)
4566 /*@globals utab@*/
4567{
4568 uentry ce = usymtab_lookupAux (utab, k);
4569
4570 return (uentry_isValid (ce));
4571}
4572
4573bool
4574 usymtab_existsGlobEither (cstring k)
4575 /*@globals globtab@*/
4576{
4577 uentry ce = usymtab_lookupAux (globtab, k);
4578
4579 return (uentry_isValid (ce));
4580}
4581# endif
4582
4583bool
4584usymtab_existsType (cstring k)
4585 /*@globals globtab@*/
4586{
4587 uentry ce = usymtab_lookupAux (globtab, k);
4588
4589 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
4590}
4591
4592bool
4593usymtab_existsTypeEither (cstring k)
4594 /*@globals globtab@*/
4595{
4596 uentry ce = usymtab_lookupAux (globtab, k);
4597
4598 return (uentry_isValid (ce) && uentry_isDatatype (ce));
4599}
4600
4601bool
4602usymtab_existsStructTag (cstring k) /*@globals globtab@*/
4603{
4604 cstring sname = makeStruct (k);
4605 uentry ce = usymtab_lookupAux (globtab, sname);
4606
4607 cstring_free (sname);
4608
4609
4610 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4611}
4612
4613bool
4614usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
4615{
4616 cstring uname = makeUnion (k);
4617 uentry ce = usymtab_lookupAux (globtab, uname);
4618
4619 cstring_free (uname);
4620
4621 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4622}
4623
4624bool
4625usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
4626{
4627 cstring ename = makeEnum (k);
4628 uentry ce = usymtab_lookupAux (globtab, ename);
4629
4630 cstring_free (ename);
4631 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4632}
4633
4634# ifndef NOLCL
4635bool usymtab_existsVar (cstring k)
4636 /*@globals utab@*/
4637{
4638 uentry ce = usymtab_lookupSafe (k);
4639
4640 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
4641}
4642# endif
4643
4644/*
4645** destructors
4646*/
4647
4648static void
4649refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
4650{
4651 if (x != NULL)
4652 {
4653 int i;
4654
4655 for (i = 0; i < nentries; i++)
4656 {
4657 sfree (x[i]);
4658 }
4659
4660 sfree (x);
4661 }
4662}
4663
4664static void
4665usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
4666 /*@globals globtab, utab, filetab@*/
4667{
4668 int i;
4669
4670 aliasTable_free (u->aliases);
dc92450f 4671 // environmentTable_free (u->environment);
616915dd 4672 refTable_free (u->reftable, u->nentries);
4673
4674 if (u == filetab || u == globtab)
4675 {
4676 for (i = 0; i < u->nentries; i++)
4677 {
4678 uentry_freeComplete (u->entries[i]);
4679 }
4680 }
4681 else
4682 {
4683 for (i = 0; i < u->nentries; i++)
4684 {
4685 uentry_free (u->entries[i]);
4686 }
4687 }
4688
4689 guardSet_free (u->guards);
4690 sfree (u->entries);
4691
4692 if (u != globtab
4693 && u != utab
4694 && u != filetab)
4695 {
4696 llassert (u->htable == NULL);
4697 sfree (u);
4698 }
4699
4700/*@-mustfree@*/
4701} /*@=mustfree@*/
4702
4703static void
4704usymtab_freeAux (/*@only@*/ usymtab u)
4705 /*@globals globtab, utab, filetab@*/
4706 /*@modifies u@*/
4707{
4708 while (u != GLOBAL_ENV)
4709 {
4710 usymtab t = u->env;
4711 usymtab_freeLevel (u);
4712 u = t;
4713 /*@-branchstate@*/
4714 }
4715 /*@=branchstate@*/
4716}
4717
4718void usymtab_free ()
4719 /*@globals killed utab, globtab, filetab@*/
4720 /*@modifies utab@*/
4721{
4722 dbgfree = TRUE;
4723 usymtab_freeAux (utab);
4724}
4725
4726static int usymtab_lexicalLevel (void) /*@globals utab@*/
4727{
4728 return (utab->lexlevel);
4729}
4730
4731bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
4732{
4733 return (utab == globtab);
4734}
4735
4736bool usymtab_inFileScope () /*@globals utab@*/
4737{
4738 return (utab->lexlevel == fileScope);
4739}
4740
4741bool usymtab_inFunctionScope () /*@globals utab@*/
4742{
4743 return (utab->lexlevel == functionScope);
4744}
4745
4746# ifndef NOLCL
4747void
4748usymtab_replaceEntry (uentry s)
4749 /*@globals utab, globtab@*/
4750 /*@modifies utab, s@*/
4751{
4752 usymtab_replaceEntryAux (utab, s);
4753}
4754# endif
4755
4756bool
4757usymtab_matchForwardStruct (usymId u1, usymId u2)
4758 /*@globals globtab@*/
4759{
4760 uentry ue1 = usymtab_getTypeEntry (u1);
4761 uentry ue2 = usymtab_getTypeEntry (u2);
4762
4763 if (uentry_isAnyTag (ue2))
4764 {
4765 ctype reptype = uentry_getType (ue1);
4766
4767 if (ctype_isPointer (reptype))
4768 {
4769 ctype repbase = ctype_getBaseType (reptype);
4770
4771 if (ctype_isUA (repbase))
4772 {
4773 typeId rtuid = ctype_typeId (repbase);
4774
4775 if (u2 == rtuid) return TRUE;
4776
4777 if (usymId_isValid (rtuid))
4778 {
4779 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
4780
4781 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
4782 }
4783 }
4784 }
4785 }
4786
4787 return FALSE;
4788}
4789
4790void usymtab_addGuards (guardSet guards)
4791 /*@modifies utab@*/
4792{
4793 utab->guards = guardSet_union (utab->guards, guards);
4794 }
4795
4796static bool usymtab_isGuardedAux (sRef s)
4797 /*@globals utab@*/
4798{
4799 usymtab tab = utab;
4800 sRef base = sRef_getRootBase (s);
4801 int lowlevel = paramsScope;
4802 int baselevel = sRef_lexLevel (base);
4803
4804 if (sRef_isCvar (base))
4805 {
4806 lowlevel = baselevel;
4807 if (lowlevel < paramsScope) lowlevel = paramsScope;
4808 }
4809
4810 while (tab->lexlevel >= lowlevel)
4811 {
4812 if (guardSet_isGuarded (tab->guards, s))
4813 {
4814 /*
4815 if (!sRef_definitelyNull (s))
4816 {
4817 sRef_setNotNull (s, fileloc_undefined);
4818 }
4819 */
4820 return TRUE;
4821 }
4822
4823 tab = usymtab_dropEnv (tab);
4824 }
4825
4826 return FALSE;
4827}
4828
4829void usymtab_unguard (sRef s) /*@modifies utab@*/
4830{
4831 usymtab tab = utab;
4832 sRef base = sRef_getRootBase (s);
4833 int lowlevel = paramsScope;
4834 int baselevel = sRef_lexLevel (base);
4835
4836 if (sRef_isCvar (base))
4837 {
4838 lowlevel = baselevel;
4839 if (lowlevel < paramsScope) lowlevel = paramsScope;
4840 }
4841
4842 while (tab->lexlevel >= lowlevel)
4843 {
4844 if (guardSet_isGuarded (tab->guards, s))
4845 {
4846 guardSet_delete (tab->guards, s);
4847 }
4848
4849 tab = usymtab_dropEnv (tab);
4850 }
4851}
4852
4853bool usymtab_isGuarded (sRef s)
4854{
4855
4856 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
4857}
4858
4859bool usymtab_isProbableNull (sRef s)
4860{
4861 return (sRef_aliasCheckSimplePred (usymtab_isProbableNullAux, s));
4862}
4863
4864bool usymtab_isProbableDeepNull (sRef s)
4865{
4866 return (sRef_deepPred (usymtab_isProbableNull, s));
4867}
4868
4869static bool usymtab_isProbableNullAux (sRef s)
4870 /*@globals utab@*/
4871{
4872 usymtab tab = utab;
4873 sRef base = sRef_getRootBase (s);
4874 int lowlevel = paramsScope;
4875
4876 if (sRef_isCvar (base))
4877 {
4878 lowlevel = sRef_lexLevel (base);
4879 if (lowlevel < paramsScope) lowlevel = paramsScope;
4880 }
4881
4882 while (tab->lexlevel >= lowlevel)
4883 {
4884 if (guardSet_isProbableNull (tab->guards, s))
4885 {
4886 return TRUE;
4887 }
4888
4889 while (tab->kind == US_CBRANCH)
4890 {
4891 tab = tab->env;
4892 }
4893
4894 llassert (usymtab_isDefined (tab));
4895
4896 if (tab->kind == US_FBRANCH)
4897 {
4898 tab = tab->env;
4899 llassert (tab->kind == US_TBRANCH);
4900 }
4901
4902 tab = tab->env;
4903 }
4904
4905 return FALSE;
4906}
4907
4908void
4909usymtab_printGuards ()
4910 /*@globals utab, globtab@*/
4911{
4912 usymtab ttab = utab;
4913
4914 while (ttab != globtab)
4915 {
4916 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
4917 guardSet_unparse (ttab->guards)));
4918 ttab = ttab->env;
4919 }
4920}
4921
4922void
4923usymtab_displayAllUses ()
4924 /*@globals utab, globtab@*/
4925{
4926 usymtab copy;
4927
4928 /* only in top scope */
4929 llassert (utab == globtab);
4930
4931 /* need a copy, so order is not messed up by sort! */
4932 copy = usymtab_shallowCopy (globtab);
4933
4934 qsort (copy->entries, (size_t)copy->nentries,
4935 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
4936
4937 usymtab_entries (copy, ue)
4938 {
4939 if (uentry_isValid (ue))
4940 {
4941 filelocList uses = uentry_getUses (ue);
4942 int size = filelocList_realSize (uses);
4943
4944 if (fileloc_isDefined (uentry_whereDefined (ue))
4945 && !fileloc_isLib (uentry_whereDefined (ue))
4946 && (size > 0))
4947 {
4948 llmsg (message ("%q (%q), %d use%p:\n %q",
4949 uentry_getName (ue),
4950 fileloc_unparse (uentry_whereDefined (ue)),
4951 size, filelocList_unparseUses (uses)));
4952 }
4953 }
4954 } end_usymtab_entries;
4955
4956 usymtab_shallowFree (copy);
4957}
4958
4959static /*@dependent@*/ /*@exposed@*/ usymtab
4960usymtab_getFileTab ()
4961 /*@globals filetab@*/
4962{
4963 llassert (filetab != NULL);
4964
4965 return filetab;
4966}
4967
4968/*@only@*/ cstring
4969usymtab_unparseStack ()
4970 /*@globals utab@*/
4971{
4972 return (usymtab_unparseStackTab (utab));
4973}
4974
4975static /*@only@*/ cstring
4976usymtab_unparseStackTab (usymtab t)
4977{
4978 bool firstOne = TRUE;
4979 cstring ret = cstring_makeLiteral ("[");
4980
4981 while (t != GLOBAL_ENV)
4982 {
4983 if (firstOne)
4984 {
4985 ret = message ("%q %q", ret, usymtab_typeName (t));
4986 firstOne = FALSE;
4987 }
4988 else
4989 {
4990 ret = message ("%q, %q", ret, usymtab_typeName (t));
4991 }
4992 t = t->env;
4993 }
4994
4995 ret = message ("%q ]", ret);
4996 return ret;
4997}
4998
4999static /*@only@*/ cstring
5000usymtab_typeName (/*@notnull@*/ usymtab t)
5001{
5002 switch (t->kind)
5003 {
5004 case US_GLOBAL: return cstring_makeLiteral ("global");
5005 case US_NORMAL: return cstring_makeLiteral ("normal");
5006 case US_TBRANCH: return cstring_makeLiteral ("true");
5007 case US_FBRANCH: return cstring_makeLiteral ("false");
5008 case US_CBRANCH: return cstring_makeLiteral ("case");
5009 case US_SWITCH: return cstring_makeLiteral ("switch");
5010 }
5011
5012 BADEXIT;
5013}
5014
dc92450f 5015// oid usymtab_testInRange (sRef s, int index) /*@globals utab;@*/
5016// {
5017// /*@i22*/
5018// /*@-globs*/
5019// environmentTable_testInRange (utab->environment, s, index);
5020// /*@=globs*/
5021// }
5022// void usymtab_postopVar (sRef sr) /*@globals utab;@*/
5023// {
5024// environmentTable_postOpvar (utab->environment, sr);
616915dd 5025
dc92450f 5026// }
5027// /* doesn't do much check here assumes checking is done before call*/
5028// void usymtab_addExactValue(sRef s1, int val)
5029// {
5030// /*@i22@*/ utab->environment = environmentTable_addExactValue (utab->environment, s1, val);
5031// }
616915dd 5032
5033void usymtab_addMustAlias (sRef s, sRef al)
5034 /*@modifies utab@*/
5035{
5036 if (sRef_isMeaningful (s) && sRef_isMeaningful (al)
5037 && !(sRef_isConst (s) || sRef_isConst (al))
5038 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al)))
5039 && !(sRef_similar (s, al)))
5040 {
5041 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5042 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5043
5044 /*
5045 ** for local variable, aliasing is symmetric
5046 */
5047
5048 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5049 {
5050 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5051 }
5052 }
5053 else
5054 {
5055 ;
5056 }
5057}
5058
5059/*
5060** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5061*/
5062
5063void usymtab_addForceMustAlias (sRef s, sRef al)
5064 /*@modifies utab@*/
5065{
5066 if (sRef_isMeaningful (s)
5067 && sRef_isMeaningful (al)
5068 && !(sRef_isConst (s) || sRef_isConst (al))
5069 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5070 {
5071 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5072 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5073
5074 /*
5075 ** for local variable, aliasing is symmetric
5076 */
5077
5078 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5079 {
5080 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5081 }
5082 }
5083 else
5084 {
5085 ;
5086 }
5087}
5088
5089void usymtab_clearAlias (sRef s)
5090 /*@modifies utab, s@*/
5091{
5092
5093 aliasTable_clearAliases (utab->aliases, s);
5094}
5095
5096sRefSet usymtab_allAliases (sRef s)
5097 /*@globals utab@*/
5098{
5099 if (sRef_isMeaningful (s))
5100 {
5101 sRefSet ret;
5102
5103
5104 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5105 aliasTable_canAlias (utab->aliases, s));
5106 return (ret);
5107 }
5108 else
5109 {
5110 return sRefSet_undefined;
5111 }
5112}
5113
5114/*@only@*/ sRefSet usymtab_canAlias (sRef s)
5115 /*@globals utab@*/
5116{
5117 if (sRef_isMeaningful (s))
5118 {
5119 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5120
5121 return res;
5122 }
5123
5124 return sRefSet_undefined;
5125}
5126
5127/*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5128 /*@globals utab@*/
5129{
5130 return (aliasTable_aliasedBy (utab->aliases, s));
5131}
5132
5133/*@only@*/ cstring usymtab_unparseAliases ()
5134 /*@globals utab@*/
5135{
5136 return (aliasTable_unparse (utab->aliases));
5137}
5138
5139/*
5140** Debugging routines:
5141** okay to leak storage here, only for debugging
5142*/
5143
5144/*@-mustfree@*/
5145
5146void
5147usymtab_printOut (void)
5148 /*@globals utab@*/
5149{
5150 int i;
5151 usymtab s = utab;
5152 int depth = 0;
5153 char *ind = mstring_copy (" ");
5154
5155 fprintf (g_msgstream, "<<< [symbol table] >>>\n");
5156
5157 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5158 {
5159 cstring tname = usymtab_typeName (s);
5160
5161 if (depth < 5)
5162 {
5163 ind[depth * 3 + 1] = '\0';
5164 }
5165
5166 fprintf (g_msgstream, "level: %d (%s)\n", s->lexlevel,
5167 cstring_toCharsSafe (tname));
5168
5169 cstring_free (tname);
5170
5171 for (i = 0; i < s->nentries; i++)
5172 {
5173 cstring us = uentry_unparseFull (s->entries[i]);
5174 fprintf (g_msgstream, "%s\n", cstring_toCharsSafe (us));
5175 cstring_free (us);
5176 }
5177
5178 if (s->reftable != NULL && s->nentries > 0)
5179 {
5180 fprintf (g_msgstream, "\t<< Ref table >>\n");
5181
5182 for (i = 0; i < s->nentries; i++)
5183 {
5184 fprintf (g_msgstream, "\t%s %3d: %d, %d\n", ind, i,
5185 s->reftable[i]->level,
5186 s->reftable[i]->index);
5187 }
5188 }
5189
5190 ind[depth * 3 + 1] = ' ';
5191 depth++;
5192 s = s->env;
5193 }
5194 fprintf (g_msgstream, "<<< end usymtab >>>\n");
5195 mstring_free (ind);
5196 return;
5197}
5198
5199void
5200usymtab_printTypes ()
5201 /*@globals globtab@*/
5202{
5203 usymtab_printAllAux (globtab);
5204}
5205
5206void
5207usymtab_printAll (void)
5208 /*@globals utab@*/
5209{
5210 usymtab_printAllAux (utab);
5211}
5212
5213static void
5214usymtab_printAllAux (usymtab s)
5215 /*@modifies g_msgstream@*/
5216{
5217 int i;
5218 int depth = 0;
5219 char *ind = mstring_copy (" ");
5220
5221 printf ("[[[ usymtab ]]]");
5222
5223 while (s != GLOBAL_ENV)
5224 {
5225 if (depth < 5)
5226 ind[depth * 3 + 1] = '\0';
5227
5228 if (s->env == GLOBAL_ENV)
5229 {
5230 int looplow;
5231
5232 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5233 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5234 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5235
5236 looplow = 0;
5237
5238 for (i = looplow; i < s->nentries; i++)
5239 {
5240 printf ("%s%3d. %s\n", ind, i,
5241 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5242 }
5243 }
5244 else
5245 {
5246 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5247 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5248 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5249
5250 for (i = 0; i < s->nentries; i++)
5251 {
5252 printf ("%s%3d %s\n", ind, i,
5253 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5254 }
5255 }
5256
5257 ind[depth * 3 + 1] = ' ';
5258 depth++;
5259 s = s->env;
5260 }
5261 printf ("----------\n");
5262}
5263
5264void
5265usymtab_printComplete ()
5266 /*@globals utab@*/
5267{
5268 int i;
5269 int depth = 0;
5270 char *ind = mstring_copy (" ");
5271 usymtab s = utab;
5272
5273 while (s != GLOBAL_ENV)
5274 {
5275 if (depth < 5)
5276 {
5277 ind[depth * 3 + 1] = '\0';
5278 }
5279
5280 if (s->env == GLOBAL_ENV)
5281 {
5282 int looplow;
5283
5284 printf ("level: %d\n", s->lexlevel);
5285
5286 looplow = 0;
5287
5288 for (i = looplow; i < s->nentries; i++)
5289 {
5290 printf ("%s%3d %s\n", ind, i,
5291 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5292 }
5293 }
5294 else
5295 {
5296 printf ("level: %d\n", s->lexlevel);
5297 for (i = 0; i < s->nentries; i++)
5298 {
5299 printf ("%s%3d %s\n", ind, i,
5300 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5301 }
5302 }
5303
5304 ind[depth * 3 + 1] = ' ';
5305 depth++;
5306 s = s->env;
5307 }
5308
5309 printf ("----------\n");
5310 mstring_free (ind);
5311}
5312
5313static /*@only@*/ cstring /*@unused@*/
5314usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5315{
5316 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5317 int i;
5318
5319 for (i = 0; i < s->nentries; i++)
5320 {
5321 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5322 }
5323
5324 c = message ("%q\n=========", c);
5325 return (c);
5326}
5327
5328static cstring /*@unused@*/ /*@only@*/
5329usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5330{
5331 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5332 bool_unparse (s->mustBreak),
5333 exitkind_unparse (s->exitCode));
5334 int i;
5335
5336 for (i = 0; i < s->nentries; i++)
5337 {
5338 sRef sr = uentry_getSref (s->entries[i]);
5339
5340 if (i == 0)
5341 {
5342 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
5343 sRef_isStateDefined (sr));
5344 }
5345 else
5346 {
5347 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
5348 sRef_isStateDefined (sr));
5349 }
5350
5351 }
5352
5353 return (c);
5354}
5355
5356void
5357usymtab_printLocal (void)
5358 /*@globals utab@*/
5359{
5360 int i;
5361 usymtab s = utab;
5362
5363 printf ("lexlevel: %d\n", s->lexlevel);
5364
5365 for (i = 0; i < s->nentries; i++)
5366 {
5367 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5368 }
5369
5370 while (s->lexlevel > 1)
5371 {
5372 s = s->env;
5373 }
5374
5375 llassert (usymtab_isDefined (s));
5376
5377 printf ("Params:\n");
5378
5379 for (i = 0; i < s->nentries; i++)
5380 {
5381 printf ("%d: %s\n", i,
5382 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5383 }
5384}
5385/*@=mustfree@*/
5386
5387static bool checkDistinctExternalName (uentry e)
5388 /*@globals globtab@*/
5389 /*@modifies *g_msgstream@*/
5390{
5391 int checklen = context_getValue (FLG_EXTERNALNAMELEN);
5392 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
5393 bool gotone = FALSE;
5394 bool extras = FALSE;
5395 bool hasError = FALSE;
5396 cstring name = uentry_rawName (e);
5397 usymtab st = globtab;
5398
5399 if (checklen == 0)
5400 {
5401 ;
5402 }
5403 else
5404 {
5405 if (uentry_isAnyTag (e))
5406 {
5407 checklen++; /* the tag marker doesn't count */
5408 }
5409 }
5410
5411 usymtab_entries (st, oe)
5412 {
5413 if (uentry_sameObject (oe, e))
5414 {
5415 continue;
5416 }
5417
5418 if (checklen == 0)
5419 {
5420 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
5421 {
5422 if (gotone)
5423 {
5424 extras = TRUE;
5425 break;
5426 }
5427
5428 if (optgenerror
5429 (FLG_DISTINCTEXTERNALNAMES,
5430 message
5431 ("External identifier %q is not distinguishable from %q "
5432 "because alphabetical case is ignored",
5433 uentry_getName (e),
5434 uentry_getName (oe)),
5435 uentry_whereLast (e)))
5436 {
5437 uentry_showWhereAny (oe);
5438 uentry_setHasNameError (oe);
5439 gotone = TRUE;
5440 }
5441 }
5442 }
5443 else
5444 {
5445 if (ignorecase)
5446 {
5447 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
5448 name, checklen))
5449 {
5450 if (gotone)
5451 {
5452 extras = TRUE;
5453 break;
5454 }
5455
5456 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
5457 {
5458 if (optgenerror
5459 (FLG_DISTINCTEXTERNALNAMES,
5460 /*@-sefparams@*/
5461 message
5462 ("External identifier %q is not distinguishable from %q "
5463 "in the first %d characters (%q)",
5464 uentry_getName (e),
5465 uentry_getName (oe),
5466 checklen,
5467 cstring_clip (uentry_getName (e), checklen)),
5468 /*@=sefparams@*/
5469 uentry_whereLast (e)))
5470 {
5471 uentry_showWhereAny (oe);
5472 uentry_setHasNameError (oe);
5473 gotone = TRUE;
5474 }
5475 }
5476 else
5477 {
5478 if (gotone)
5479 {
5480 extras = TRUE;
5481 break;
5482 }
5483
5484 if (optgenerror
5485 (FLG_DISTINCTEXTERNALNAMES,
5486 message
5487 ("External identifier %q is not distinguishable from %q "
5488 "in the first %d characters because alphabetical case "
5489 "is ignored",
5490 uentry_getName (e),
5491 uentry_getName (oe),
5492 checklen),
5493 uentry_whereLast (e)))
5494 {
5495 uentry_showWhereAny (oe);
5496 uentry_setHasNameError (oe);
5497 gotone = TRUE;
5498 }
5499 }
5500 }
5501 }
5502 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
5503 {
5504 if (gotone)
5505 {
5506 extras = TRUE;
5507 break;
5508 }
5509
5510 if (optgenerror
5511 (FLG_DISTINCTEXTERNALNAMES,
5512 /*@-sefparams@*/
5513 message
5514 ("External identifier %q is not distinguishable from %q "
5515 "in the first %d characters (%q)",
5516 uentry_getName (e),
5517 uentry_getName (oe),
5518 checklen,
5519 cstring_clip (uentry_getName (e), checklen)),
5520 /*@=sefparams@*/
5521 uentry_whereLast (e)))
5522 {
5523 uentry_showWhereAny (oe);
5524 uentry_setHasNameError (oe);
5525 gotone = TRUE;
5526 }
5527 }
5528 else
5529 {
5530 ; /* okay */
5531 }
5532 }
5533 } end_usymtab_entries ;
5534
5535 hasError = gotone;
5536
5537 if (extras)
5538 {
5539 llgenindentmsgnoloc
5540 (cstring_makeLiteral ("One or more additional "
5541 "indistinguishable external "
5542 "names not reported"));
5543 }
5544
5545 return hasError;
5546}
5547
5548static bool checkDistinctInternalName (uentry e)
5549 /*@globals utab@*/
5550 /*@modifies *g_msgstream@*/
5551{
5552 usymtab ttab = utab;
5553 cstring name = uentry_rawName (e);
5554 int numchars = context_getValue (FLG_INTERNALNAMELEN);
5555 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
5556 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
5557
5558 if (uentry_isAnyTag (e) && (numchars != 0))
5559 {
5560 numchars++; /* the tag marker doesn't count */
5561 }
5562
5563 while (usymtab_isDefined (ttab))
5564 {
5565 usymtab_entries (ttab, oe)
5566 {
5567 if (uentry_sameObject (oe, e))
5568 {
5569 /*@innercontinue@*/ continue;
5570 }
5571
5572 switch (cstring_genericEqual
5573 (name, uentry_rawName (oe),
5574 numchars, caseinsensitive, lookalike))
5575 {
5576 case CGE_DISTINCT: /* okay */
5577 /*@switchbreak@*/
5578 break;
5579 case CGE_SAME:
5580 if (cstring_equal (name, uentry_rawName (oe)))
5581 {
5582 ; /* got a shadow error */
5583 }
5584 else
5585 {
5586 if (optgenerror
5587 (FLG_DISTINCTINTERNALNAMES,
5588 /*@-sefparams@*/
5589 message
5590 ("Internal identifier %q is not distinguishable from %q "
5591 "in the first %d characters (%q)",
5592 uentry_getName (e),
5593 uentry_getName (oe),
5594 numchars,
5595 cstring_clip (uentry_getName (e), numchars)),
5596 /*@=sefparams@*/
5597 uentry_whereLast (e)))
5598 {
5599 uentry_showWhereAny (oe);
5600 uentry_setHasNameError (oe);
5601 return TRUE;
5602 }
5603 }
5604 /*@switchbreak@*/
5605 break;
5606 case CGE_CASE:
5607 if (numchars == 0
5608 || (cstring_length (name) <= numchars))
5609 {
5610 if (optgenerror
5611 (FLG_DISTINCTINTERNALNAMES,
5612 message
5613 ("Internal identifier %q is not distinguishable from %q "
5614 "without case sensitivity",
5615 uentry_getName (e),
5616 uentry_getName (oe)),
5617 uentry_whereLast (e)))
5618 {
5619 uentry_showWhereAny (oe);
5620 uentry_setHasNameError (oe);
5621 return TRUE;
5622 }
5623 }
5624 else
5625 {
5626 if (optgenerror
5627 (FLG_DISTINCTINTERNALNAMES,
5628 message
5629 ("Internal identifier %q is not distinguishable from %q "
5630 "in the first %d characters without case sensitivity",
5631 uentry_getName (e),
5632 uentry_getName (oe),
5633 numchars),
5634 uentry_whereLast (e)))
5635 {
5636 uentry_showWhereAny (oe);
5637 uentry_setHasNameError (oe);
5638 return TRUE;
5639 }
5640 }
5641 /*@switchbreak@*/
5642 break;
5643 case CGE_LOOKALIKE:
5644 if (numchars == 0
5645 || (cstring_length (name) <= numchars))
5646 {
5647 if (optgenerror
5648 (FLG_DISTINCTINTERNALNAMES,
5649 message
5650 ("Internal identifier %q is not distinguishable from %q "
5651 "except by lookalike characters",
5652 uentry_getName (e),
5653 uentry_getName (oe)),
5654 uentry_whereLast (e)))
5655 {
5656 uentry_showWhereAny (oe);
5657 uentry_setHasNameError (oe);
5658 return TRUE;
5659 }
5660 }
5661 else
5662 {
5663 if (optgenerror
5664 (FLG_DISTINCTINTERNALNAMES,
5665 message
5666 ("Internal identifier %q is not distinguishable from %q "
5667 "in the first %d characters except by lookalike characters",
5668 uentry_getName (e),
5669 uentry_getName (oe),
5670 numchars),
5671 uentry_whereLast (e)))
5672 {
5673 uentry_showWhereAny (oe);
5674 uentry_setHasNameError (oe);
5675 return TRUE;
5676 }
5677 }
5678 }
5679 } end_usymtab_entries ;
5680
5681 ttab = ttab->env;
5682 }
5683
5684 return FALSE;
5685}
5686
5687void usymtab_checkDistinctName (uentry e, int scope)
5688 /*@globals utab, globtab@*/
5689{
5690 bool hasError = FALSE;
5691 fileloc where = uentry_whereLast (e);
5692
5693 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
5694 {
5695 if (scope == globScope)
5696 {
5697 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
5698 {
5699 hasError = checkDistinctExternalName (e);
5700 }
5701 }
5702
5703 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
5704 {
5705 hasError = checkDistinctInternalName (e);
5706 }
5707 }
5708
5709 if (hasError)
5710 {
5711 uentry_setHasNameError (e);
5712 }
5713}
5714
This page took 1.419239 seconds and 5 git commands to generate.