2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
27 ** Lexically scoped symbol table.
29 ** Unlike a normal symbol table, this table splits to reflect branches.
31 ** This is necessary since symbol table entries also reflect
32 ** some state information, like initialization, that may be
33 ** different on different branches.
35 ** For each control structure we split:
37 ** { } - a normal scope (no control) US_NORMAL
39 ** if <pred> { } - US_TBRANCH true branch
40 ** while <pred> { } US_FBRANCH else branch
42 ** switch <pred> { } - US_SWITCH
44 ** case x: - case scope US_CBRANCH
45 ** Should be kept in a separate table, because of
49 # include "splintMacros.nf"
51 # include "structNames.h"
52 # include "exprChecks.h"
53 # include "transferChecks.h"
56 /* Needed to install macros when loading libraries */
59 # include "cpperror.h"
64 ** Keep track of type definitions inside a function.
67 static uentryList functypes
= uentryList_undefined
;
69 static bool dbgfree
= FALSE
;
70 static bool dbgload
= TRUE
;
75 ** Hack to prevent shadow errors from appearing when function parameters
76 ** are entered into a new scope.
79 static bool noshadowerror
= FALSE
;
82 ** Constraint: static variables can live in 1 or > 2.
84 ** except for tags. All tags must be at the global level.
85 ** Static tags are handled in a kludgey way.
89 ** utab is the universal symbol table
90 ** globtab is the global environment of utab
91 ** oldtab is needed for conversions in dumping (after sorting the table)
93 ** there can be only one usymtab!
96 static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab
;
98 /* Reachable environments from from utab */
99 static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab
;
100 static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab
;
102 /* Used for sorting for dumpage. */
103 static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab
;
105 static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
106 static bool usymtab_isAltDefinitelyNull (sRef p_s
) /*@globals utab@*/ ;
107 static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x
, int p_nentries
);
108 static ctype
usymtab_suFieldsType (uentryList p_f
, bool p_isStruct
) /*@globals globtab@*/ ;
110 static void usymtab_freeAux (/*@only@*/ usymtab p_u
)
111 /*@globals globtab, utab, filetab@*/
115 extern int usymtab_getCurrentDepth (void) /*@globals utab@*/
117 return utab
->lexlevel
;
122 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u
)
123 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
125 static bool usymtab_isDefinitelyNullAux (sRef p_s
) /*@globals utab@*/ ;
126 static /*@only@*/ cstring
usymtab_unparseStackTab (usymtab p_t
);
127 static /*@exposed@*/ /*@dependent@*/ uentry
128 usymtab_getRefTab (/*@notnull@*/ usymtab p_u
, int p_level
, usymId p_index
);
131 /* These are not used anymore... */
132 static /*@unused@*/ /*@only@*/ cstring
133 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s
);
134 static /*@unused@*/ /*@only@*/ cstring
135 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s
);
138 static /*@only@*/ cstring
usymtab_typeName (/*@notnull@*/ usymtab p_t
);
139 static void usymtab_handleParams (void)
140 /*@globals utab, globtab, filetab@*/
141 /*@modifies utab@*/ ;
143 static /*@exposed@*/ /*@dependent@*/ uentry
144 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s
, cstring p_k
);
145 static /*@exposed@*/ /*@dependent@*/ usymtab
146 usymtab_dropEnv (/*@notnull@*/ usymtab p_s
);
147 static /*@exposed@*/ /*@dependent@*/ uentry
148 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s
, int p_level
, usymId p_index
);
150 static /*@exposed@*/ /*@dependent@*/ uentry
151 usymtab_lookupQuietAux (usymtab p_s
, cstring p_k
, bool p_noalt
);
153 static /*@exposed@*/ /*@dependent@*/ uentry
154 usymtab_lookupQuiet (usymtab p_s
, cstring p_k
);
156 static /*@exposed@*/ /*@dependent@*/ uentry
157 usymtab_lookupQuietNoAlt (usymtab p_s
, cstring p_k
);
159 static void usymtab_printAllAux (usymtab p_s
) /*@modifies g_warningstream@*/ ;
161 /*@function bool usymtab_indexFound (usymId) @*/
162 # define usymtab_indexFound(u) ((u) != usymId_notfound)
164 static usymId
usymtab_getIndex (/*@notnull@*/ usymtab p_s
, cstring p_k
);
165 static /*@exposed@*/ uentry
usymtab_fetchIndex (/*@notnull@*/ usymtab p_s
, usymId p_ui
);
166 static /*@exposed@*/ uentry
usymtab_lookupAux (usymtab p_s
, cstring p_k
);
168 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/
169 usymtab
usymtab_getFileTab (void) /*@globals filetab@*/ ;
171 static int refTable_lookup (/*@notnull@*/ usymtab p_ut
, int p_level
, usymId p_index
);
172 static bool usymtab_mustBreak (usymtab p_s
);
173 static bool usymtab_mustEscape (usymtab p_s
);
175 static void recordFunctionType (uentry ue
)
177 llassert (uentry_isDatatype (ue
) || uentry_isAnyTag (ue
)
178 || uentry_isEnumConstant (ue
));
179 DPRINTF (("Function type: %s", uentry_unparseFull (ue
)));
181 functypes
= uentryList_add (functypes
, ue
);
185 static void clearFunctionTypes (void)
186 /*@modifies globtab@*/
188 uentryList_elements (functypes
, el
)
190 if (cstring_isDefined (uentry_rawName (el
)))
192 if (cstringTable_isDefined (globtab
->htable
))
194 cstringTable_remove (globtab
->htable
, uentry_rawName (el
));
197 uentry_setName (el
, cstring_undefined
);
201 llassert (uentry_isValid (el
));
202 el
->sref
= sRef_undefined
;
203 /*@noaccess uentry@*/
204 } end_uentryList_elements
;
206 uentryList_clear (functypes
);
209 static /*@falsewhennull@*/ bool usymtab_isBranch (usymtab u
)
211 return (usymtab_isDefined (u
) &&
212 (u
->kind
== US_TBRANCH
|| u
->kind
== US_FBRANCH
213 || u
->kind
== US_CBRANCH
|| u
->kind
== US_SWITCH
));
216 static bool usymtab_mustBreak (usymtab s
)
218 llassert (s
!= GLOBAL_ENV
);
219 return (s
->mustBreak
);
222 static bool usymtab_mustEscape (usymtab s
)
224 llassert (s
!= GLOBAL_ENV
);
225 return (exitkind_mustEscape (s
->exitCode
));
228 void usymtab_setMustBreak (void)
231 llassert (utab
!= GLOBAL_ENV
);
232 utab
->mustBreak
= TRUE
;
235 void usymtab_setExitCode (exitkind ex
)
238 llassert (utab
!= GLOBAL_ENV
);
242 if (exitkind_mustEscape (ex
))
244 utab
->mustBreak
= TRUE
;
248 bool usymtab_isAltDefinitelyNullDeep (sRef s
)
250 return (sRef_deepPred (usymtab_isAltDefinitelyNull
, s
));
253 static bool usymtab_isAltDefinitelyNull (sRef s
)
261 llassert (utab
->env
!= NULL
);
263 /*@-mods@*/ /* These modifications are cancelled. */
264 utab
->guards
= utab
->env
->guards
;
265 utab
->env
->guards
= t
;
268 llassert (usymtab_isDefined (utab
));
269 res
= usymtab_isDefinitelyNull (s
);
272 ** This reports a spurious error. It is okay, because of
273 ** the nesting relationship of usymtab environments.
276 /*@-mods@*/ /* Cancelling modifications. */
277 /*@i1@*/ utab
->env
->guards
= utab
->guards
;
278 /*@i1@*/ utab
->guards
= t
;
284 static /*@notnull@*/ /*@special@*/ usymtab
285 usymtab_create (uskind kind
, /*@keep@*/ usymtab env
, bool nextlevel
)
287 /*@post:isnull result->htable, result->guards, result->aliases@*/
289 usymtab t
= (usymtab
) dmalloc (sizeof (*t
));
292 t
->nspace
= CBASESIZE
;
293 t
->entries
= (uentry
*) dmalloc (sizeof (*t
->entries
) * CBASESIZE
);
295 /* We only use a reftable for branch-level symbol tables. */
297 t
->reftable
= (nextlevel
299 : (refentry
*) dmalloc (sizeof (*t
->reftable
) * CBASESIZE
));
302 t
->lexlevel
= (env
== GLOBAL_ENV
? 0 : env
->lexlevel
) + (nextlevel
? 1 : 0);
307 t
->guards
= guardSet_undefined
;
308 t
->aliases
= aliasTable_undefined
;
310 t
->mustBreak
= FALSE
;
311 t
->exitCode
= XK_NEVERESCAPE
;
313 DPRINTF (("Create usymtab [%p]", t
));
321 static /*@only@*/ /*@notnull@*/ usymtab
322 usymtab_createRoot (void) /*@modifies nothing@*/
324 usymtab u
= (usymtab
) dmalloc (sizeof (*u
));
327 u
->nspace
= CGLOBBASESIZE
;
328 u
->entries
= (uentry
*) dmalloc (sizeof (*u
->entries
) * CGLOBBASESIZE
);
331 u
->htable
= cstringTable_create (CGLOBHASHSIZE
);
334 u
->guards
= guardSet_new ();
335 u
->aliases
= aliasTable_new ();
337 u
->mustBreak
= FALSE
;
338 u
->exitCode
= XK_NEVERESCAPE
;
345 usymtab_initMod (void)
346 /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
347 /*@modifies utab, globtab, filetab, oldtab @*/
349 utab
= usymtab_createRoot ();
351 filetab
= usymtab_undefined
;
352 oldtab
= usymtab_undefined
;
356 usymtab_destroyMod (void)
357 /*@modifies utab, globtab, filetab@*/
358 /*@globals killed utab@*/
360 DPRINTF (("Destroy usymtab [%p]: %d", utab
, utab
->nentries
));
364 usymtab_freeAux (utab
);
365 utab
= usymtab_undefined
;
367 } /*@=globstate@*/ /* Splint cannot tell that utab is killed */
370 usymtab_initGlobalMarker (void) /*@globals globtab@*/
372 if (uentry_isValid (usymtab_lookupAux (globtab
, GLOBAL_MARKER_NAME
)))
374 ; /* Already entered from load table. */
378 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
383 ** utab should be empty? (requires?)
385 ** Adds bool types to symbol table (these are built in for now)
386 ** Only do this is there is no library!
390 usymtab_initBool (void)
392 DPRINTF (("Init bool!"));
394 if (context_getFlag (FLG_NOLIB
))
396 ctype boolt
= ctype_bool
;
397 /* evs 2000-07-24: bool is now treated as abstract (always) */
399 uentry boolentry
= uentry_makeBoolDatatype (qual_createAbstract ());
400 usymtab_supGlobalEntry (boolentry
);
401 context_addBoolAccess ();
404 ** We supply values 0 and 1 for the constants, so things like
405 ** while (TRUE) can be interpreted correctly.
408 usymtab_supGlobalEntry
409 (uentry_makeConstantValue (context_getFalseName (), boolt
,
410 fileloc_getBuiltin (), FALSE
,
411 multiVal_makeInt (0)));
413 usymtab_supGlobalEntry
414 (uentry_makeConstantValue (context_getTrueName (), boolt
,
415 fileloc_getBuiltin (), FALSE
,
416 multiVal_makeInt (1)));
425 usymtab_grow (/*@notnull@*/ usymtab s
)
428 o_uentry
*oldsyms
= s
->entries
;
430 s
->nspace
= CBASESIZE
;
431 s
->entries
= (uentry
*) dmalloc (sizeof (*s
->entries
)
432 * (s
->nentries
+ s
->nspace
));
434 for (i
= 0; i
< s
->nentries
; i
++)
436 s
->entries
[i
] = oldsyms
[i
];
441 if (s
->reftable
!= NULL
)
443 refTable oldRefs
= s
->reftable
;
445 s
->reftable
= (refentry
*) dmalloc (sizeof (*s
->reftable
)
446 * (s
->nentries
+ CBASESIZE
+ 1));
448 for (i
= 0; i
< s
->nentries
; i
++)
450 s
->reftable
[i
] = oldRefs
[i
];
461 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s
, /*@keep@*/ uentry e
)
463 if (!(s
->lexlevel
> fileScope
|| !sRef_modInFunction ()))
465 if (uentry_isDatatype (e
)
466 || uentry_isFunction (e
)
467 || uentry_isAnyTag (e
)
468 || uentry_isEnumConstant (e
)
469 || context_inMacro ())
472 ** Not a bug. Code like,
473 ** int f (void) { typedef int tint; ... }
477 /* was nothing here! */
478 /*@i@*/ e
->sref
= sRef_saveCopy (e
->sref
);
483 (cstring_makeLiteral ("Declaration outside function scope"));
485 llcontbug (message ("%s: inconsistent state (lexlevel = %d, "
486 "modFunction = %s) adding: %q", cstring_fromChars (__func__
),
487 s
->lexlevel
, bool_unparse (sRef_modInFunction ()),
488 uentry_unparse (e
)));
489 sRef_setGlobalScope ();
490 /* make sure the sRef is not bashed! */
491 /*@i@*/ e
->sref
= sRef_saveCopy (e
->sref
);
501 s
->entries
[s
->nentries
] = e
;
504 if (s
== globtab
|| s
== filetab
)
506 if (!fileloc_isLib (g_currentloc
))
508 uentry_tallyAnnots (e
, AN_UNKNOWN
);
513 if (cstringTable_isDefined (s
->htable
))
515 cstringTable_insert (s
->htable
, cstring_copy (uentry_rawName (e
)), s
->nentries
);
521 static /*@observer@*/ uentry
/*@alt void@*/
522 usymtab_addEntryBase (/*@notnull@*/ usymtab s
, /*@only@*/ uentry e
)
525 ** In theory, we shouldn't need this test because it this is
526 ** only called when a library is being read, and it shouldn't
527 ** ever have a duplicate entry. In practice, its safer to
528 ** leave it in, though.
533 if (uentry_isValid (old
= usymtab_lookupQuiet (s
, uentry_rawName (e
))))
535 DPRINTF (("Duplicate entry: %s", uentry_unparse (e
)));
536 uentry_free (e
); /* duplicate */
541 usymId thisentry
= usymId_fromInt (s
->nentries
);
543 if (uentry_isVar (e
))
546 (e
, sRef_makeCvar (globScope
, thisentry
,
548 stateInfo_makeLoc (uentry_whereLast (e
), SA_DECLARED
)));
551 usymtab_addEntryQuiet (s
, e
);
557 static /*@observer@*/ uentry
/*@alt void@*/
558 usymtab_addEntryAlways (/*@notnull@*/ usymtab s
, /*@only@*/ uentry e
)
561 ** In theory, we shouldn't need this test because it this is
562 ** only called when a library is being read, and it shouldn't
563 ** ever have a duplicate entry. In practice, its safer to
564 ** leave it in, though.
568 usymId thisentry
= usymId_fromInt (s
->nentries
);
570 if (uentry_isValid (old
= usymtab_lookupQuiet (s
, uentry_rawName (e
))))
573 (message ("Duplicate entry in load library: %s. "
574 "Old entry: %q. New entry: %q",
576 uentry_unparseFull (old
),
577 uentry_unparseFull (e
)));
579 uentry_setName (e
, message ("__x_%s", uentry_rawName (e
)));
580 /* This shouldn't happen...unless the library is bad! */
584 if (uentry_isVar (e
) && !uentry_isGlobalMarker (e
))
587 (e
, sRef_makeCvar (globScope
, thisentry
,
589 stateInfo_makeLoc (uentry_whereLast (e
), SA_DECLARED
)));
592 usymtab_addEntryQuiet (s
, e
);
597 usymtab_addEntryAux (/*@notnull@*/ usymtab st
, /*@keep@*/ uentry e
, bool isSref
)
598 /*@globals globtab@*/
601 usymId thisentry
= usymId_fromInt (st
->nentries
);
603 llassert (!uentry_isElipsisMarker (e
));
607 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
610 llassertprint (uentry_isAnyTag (e
) ? st
== globtab
: TRUE
,
611 ("non-global tag: %s / %d", uentry_unparseFull (e
), st
->lexlevel
));
613 if (st
->lexlevel
== fileScope
614 && (!(uentry_isStatic (e
)) || uentry_isAnyTag (e
)))
619 if (st
->kind
== US_CBRANCH
)
621 /* variables in a case branch (and not in a block inside the case branch)
622 * must be added in the environment incapsulating the case branch. */
623 st
= usymtab_dropEnv (st
);
628 ctype ct
= uentry_getType (e
);
630 if (uentry_isFunction (e
) && ctype_isFunction (ct
))
632 ct
= ctype_getReturnType (ct
);
635 if (uentry_isStatic (e
))
637 sRef sr
= sRef_makeCvar (st
->lexlevel
, thisentry
, ct
,
638 stateInfo_makeLoc (uentry_whereLast (e
), SA_DECLARED
));
640 if (sRef_isStack (sr
) || sRef_isLocalState (sr
))
642 sRef_setAliasKind (sr
, AK_STATIC
, uentry_whereLast (e
));
643 sRef_setDefined (sr
, uentry_whereLast (e
));
646 uentry_setSref (e
, sr
);
651 (e
, sRef_makeCvar (st
->lexlevel
, thisentry
, ct
,
652 stateInfo_makeLoc (uentry_whereLast (e
), SA_DECLARED
)));
656 if (uentry_isDatatype (e
))
658 uentry_setDatatype (e
, typeId_fromUsymId (thisentry
));
661 if (uentry_isFunction (e
))
663 ctype ct
= uentry_getType (e
);
665 if (ctype_isFunction (ct
)
666 && uentryList_isMissingParams (ctype_argsFunction (ct
)))
668 if (uentry_isDeclared (e
))
672 message ("Function %q declared without parameter list",
674 uentry_whereDeclared (e
));
680 message ("Function %q specified without parameter list",
682 uentry_whereSpecified (e
));
687 if (st
== globtab
&& !uentry_isSpecified (e
))
689 exprChecks_checkExport (e
);
692 uentry_checkName (e
);
694 usymtab_addEntryQuiet (st
, e
);
695 DPRINTF (("Adding entry: [%p] %s", e
, uentry_unparseFull (e
)));
700 usymtab_addEntry (uentry e
)
701 /*@globals utab, globtab@*/
702 /*@modifies utab, e@*/
704 llassertprint (!usymtab_exists (uentry_rawName (e
)),
705 ("Entry already exists: %s", uentry_unparse (e
)));
707 return usymtab_addEntryAux (utab
, e
, FALSE
);
711 usymtab_addGlobalEntry (uentry e
)
712 /*@modifies globtab, e@*/
714 DPRINTF (("Add global: %s / %s", uentry_unparse (e
), bool_unparse (uentry_isForward (e
))));
716 (void) usymtab_addEntryAux (globtab
, e
, FALSE
);
720 ** supercede and replace entry use elements of entries array, and
721 ** assign an element to a new value, and then free the old value.
722 ** Need -deparrays to avoid errors for this.
728 usymtab_supEntryAux (/*@notnull@*/ usymtab st
,
729 /*@only@*/ uentry e
, bool isSref
)
730 /*@globals globtab, filetab@*/
731 /*@modifies st, globtab, e@*/
733 cstring ename
= uentry_rawName (e
);
734 bool staticEntry
= FALSE
;
737 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e
)));
739 /* static tags in global scope */
740 if (st
->lexlevel
== fileScope
741 && (!(uentry_isStatic (e
)) || uentry_isAnyTag (e
)))
743 eindex
= usymtab_getIndex (st
, ename
);
745 if (usymtab_indexFound (eindex
))
747 uentry ce
= st
->entries
[eindex
];
751 message ("%s %q shadows static declaration",
752 ekind_capName (uentry_getKind (e
)),
754 uentry_whereDeclared (e
)))
756 uentry_showWhereLast (ce
);
759 if (eindex
== usymId_fromInt (st
->nentries
- 1))
765 st
->entries
[eindex
] = st
->entries
[st
->nentries
- 1];
768 if (cstringTable_isDefined (st
->htable
))
770 cstringTable_replaceKey (st
->htable
, uentry_rawName (ce
),
771 cstring_copy (uentry_rawName (e
)));
781 if (uentry_isStatic (e
)) {
782 if (uentry_isFunction (e
)) {
784 ** Static function declarations are at the file level,
785 ** even if they are in a deeper scope.
788 st
= usymtab_getFileTab ();
791 if (!uentry_isAnyTag (e
) && st
== globtab
)
793 st
= usymtab_getFileTab ();
795 DPRINTF (("Static entry!"));
800 eindex
= usymtab_getIndex (st
, ename
);
802 if (usymtab_indexFound (eindex
))
804 uentry ce
= st
->entries
[eindex
];
806 DPRINTF (("Found entry: %s", uentry_unparse (ce
)));
808 if (uentry_isPriv (ce
)
809 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
810 || (uentry_isStatic (ce
)
811 && uentry_isAnyTag (ce
)
812 && (uentry_isDeclared (ce
)
813 && !fileloc_sameFile (uentry_whereDefined (ce
),
814 uentry_whereDefined (e
)))))
818 ** if overloading import should do some checks!
821 llassert ((st
->lexlevel
> fileScope
|| !sRef_modInFunction ()));
823 DPRINTF (("Overloading!"));
825 st
->entries
[eindex
] = e
;
827 if (uentry_isDatatype (e
))
829 uentry_setDatatype (e
, typeId_fromUsymId (eindex
));
832 if (st
== globtab
&& !uentry_isSpecified (e
))
834 exprChecks_checkExport (e
);
837 if (cstringTable_isDefined (st
->htable
))
839 cstringTable_replaceKey (st
->htable
, uentry_rawName (ce
),
840 cstring_copy (uentry_rawName (e
)));
846 else if (uentry_isSpecified (ce
))
848 if (uentry_isSpecified (e
))
850 DPRINTF (("Here we are: %s", uentry_unparseFull (e
)));
852 if (fileloc_isImport (uentry_whereSpecified (ce
)))
854 if (cstringTable_isDefined (st
->htable
))
856 cstringTable_replaceKey (st
->htable
,
858 cstring_copy (uentry_rawName (e
)));
862 st
->entries
[eindex
] = e
;
865 if (uentry_isDatatype (e
)) uentry_setDatatype (e
, typeId_fromUsymId (eindex
));
869 if (fileloc_isImport (uentry_whereSpecified (e
)))
875 /* Respecification errors already reported */
876 DPRINTF (("Respecification: %s / %s",
877 fileloc_unparse (uentry_whereSpecified (e
)),
878 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e
)))));
880 if (uentry_isDatatype (e
))
882 uentry_setDatatype (e
, typeId_fromUsymId (eindex
));
885 if (cstringTable_isDefined (st
->htable
))
887 cstringTable_replaceKey (st
->htable
,
889 cstring_copy (uentry_rawName (e
)));
892 llassert ((st
->lexlevel
> fileScope
|| !sRef_modInFunction ()));
894 st
->entries
[eindex
] = e
;
899 else /* e not specified */
901 DPRINTF (("Merging..."));
903 if (uentry_isDeclared (ce
))
906 No - this can happen for internal typedefs
907 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
910 DPRINTF (("Merge defn"));
911 uentry_mergeDefinition (ce
, e
);
916 No - this can happen for internal typedefs
917 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
920 DPRINTF (("Merge entries..."));
921 uentry_mergeEntries (ce
, e
);
922 DPRINTF (("After: %s", uentry_unparseFull (ce
)));
926 else /* ce not specified */
928 if (!(st
->lexlevel
> fileScope
|| !sRef_modInFunction ()))
930 if (uentry_isDatatype (e
) || uentry_isAnyTag (e
)
931 || uentry_isEnumConstant (e
)
932 || uentry_isStatic (e
)) /* bug fix from Brian St. Pierre */
935 ** Not a bug. Code like,
936 ** int f (void) { typedef int tint; ... }
942 llcontbug (message ("%s: inconsistent state (lexlevel = %d,"
943 " modFunction = %s) adding: %q", cstring_fromChars (__func__
),
944 st
->lexlevel
, bool_unparse (sRef_modInFunction ()),
945 uentry_unparse (e
)));
947 if (sRef_modInFunction ())
949 /* make sure the sRef is not bashed! */
950 /*@i@*/ e
->sref
= sRef_saveCopy (e
->sref
);
955 DPRINTF (("Merge.."));
956 uentry_mergeDefinition (ce
, e
);
961 ctype ct
= uentry_getType (ce
);
963 if (uentry_isFunction (ce
) && ctype_isFunction (ct
))
965 ct
= ctype_getReturnType (ct
);
969 (ce
, sRef_makeCvar (st
->lexlevel
, eindex
, ct
,
970 stateInfo_makeLoc (uentry_whereLast (ce
), SA_DECLARED
)));
973 else /* no previous entry */
977 if (st
->lexlevel
== globScope
978 && !uentry_isStatic (e
)
979 && !uentry_isExtern (e
)
980 && usymtab_isDefined (filetab
))
983 ** check if there is a static entry: (i.e.,
990 eindex
= usymtab_getIndex (filetab
, ename
);
992 if (usymtab_indexFound (eindex
))
994 uentry ce
= filetab
->entries
[eindex
];
996 uentry_setStatic (e
);
997 uentry_mergeDefinition (ce
, e
);
1003 outer
= usymtab_lookupQuiet (st
->env
, ename
);
1005 DPRINTF (("New : [%p] %s", e
, uentry_unparseFull (e
)));
1006 DPRINTF (("Outer: [%p] %s", outer
, uentry_unparseFull (outer
)));
1009 ** no previous definition, add the new one
1013 && uentry_isValid (outer
)
1014 && !(uentry_isYield (e
) || uentry_isYield (outer
))
1015 && fileloc_isDefined (uentry_whereLast (e
))
1016 && !fileloc_isXHFile (uentry_whereLast (e
))
1017 && fileloc_isDefined (uentry_whereLast (outer
))
1018 && !fileloc_isXHFile (uentry_whereLast (outer
)))
1020 if (!uentry_sameKind (outer
, e
))
1026 if (ctype_isUnknown (uentry_getType (outer
))
1027 || uentry_isForward (outer
))
1035 message ("%s %q shadows outer declaration",
1036 ekind_capName (uentry_getKind (e
)),
1037 uentry_getName (e
)),
1038 uentry_whereLast (e
)))
1040 uentry_showWhereLast (outer
);
1046 if (st
== globtab
&& context_getFlag (FLG_NEWDECL
))
1050 message ("New declaration: %q", uentry_getName (e
)),
1051 uentry_whereLast (e
));
1054 eindex
= usymtab_addEntryAux (st
, e
, isSref
);
1058 return (staticEntry
? usymId_invalid
: eindex
);
1062 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st
, /*@only@*/ uentry e
)
1063 /*@globals globtab@*/ /*@modifies st, e@*/
1065 cstring ename
= uentry_rawName (e
);
1068 /* static tags in global scope */
1069 eindex
= usymtab_getIndex (st
, ename
);
1071 if (usymtab_indexFound (eindex
))
1073 uentry ce
= st
->entries
[eindex
];
1075 if (cstringTable_isDefined (st
->htable
))
1077 cstringTable_replaceKey (st
->htable
, uentry_rawName (ce
),
1078 cstring_copy (uentry_rawName (e
)));
1082 st
->entries
[eindex
] = e
;
1086 eindex
= usymtab_addEntryAux (st
, e
, FALSE
);
1092 void usymtab_supEntry (uentry e
)
1093 /*@globals utab, filetab, globtab@*/
1094 /*@modifies utab, globtab, e@*/
1096 (void) usymtab_supEntryAux (utab
, e
, FALSE
);
1100 ** this should be lots more efficient!
1103 static /*@exposed@*/ uentry
1104 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab
,
1105 /*@only@*/ uentry e
, bool isref
)
1106 /*@globals globtab, filetab@*/
1107 /*@modifies tab, globtab, e@*/
1109 cstring rawName
= cstring_copy (uentry_rawName (e
));
1110 bool stat
= (tab
== globtab
) && uentry_isStatic (e
);
1113 (void) usymtab_supEntryAux (tab
, e
, isref
);
1117 ret
= usymtab_lookupAux (filetab
, rawName
);
1121 ret
= usymtab_lookupAux (tab
, rawName
);
1123 if (uentry_isInvalid (ret
) && usymtab_isDefined (filetab
))
1125 ret
= usymtab_lookupAux (filetab
, rawName
);
1129 cstring_free (rawName
);
1133 /*@dependent@*/ /*@exposed@*/ uentry
1134 usymtab_supEntryReturn (/*@only@*/ uentry e
)
1135 /*@globals utab, filetab, globtab@*/
1136 /*@modifies utab, globtab, e@*/
1138 return (usymtab_supEntryReturnAux (utab
, e
, FALSE
));
1141 /*@dependent@*/ /*@exposed@*/ uentry
1142 usymtab_supEntrySrefReturn (/*@only@*/ uentry e
)
1143 /*@globals utab, globtab, filetab@*/
1144 /*@modifies utab, globtab, e@*/
1146 return (usymtab_supEntryReturnAux (utab
, e
, TRUE
));
1149 /*@dependent@*/ /*@exposed@*/ uentry
1150 usymtab_supGlobalEntryReturn (uentry e
)
1151 /*@globals globtab, filetab@*/
1152 /*@modifies globtab, e@*/
1156 ret
= usymtab_supEntryReturnAux (globtab
, e
, FALSE
);
1159 ** We need to keep track of internal function declarations, so
1160 ** we can remove them from the symbol table after exiting this
1161 ** function. This is a bit bogus, of course.
1164 if (sRef_modInFunction ())
1166 recordFunctionType (ret
);
1173 usymtab_supTypeEntry (/*@only@*/ uentry e
)
1174 /*@globals globtab, filetab@*/
1175 /*@modifies globtab, e@*/
1180 if (uentry_isAbstractDatatype (e
))
1182 typeId tid
= usymtab_supAbstractTypeEntry (e
, FALSE
);
1183 ret
= ctype_createAbstract (tid
);
1184 uid
= typeId_toUsymId (tid
);
1188 uid
= usymtab_supEntryAux (globtab
, e
, FALSE
);
1189 ret
= ctype_createUser (typeId_fromUsymId (uid
));
1192 if (sRef_modInFunction ())
1194 recordFunctionType (globtab
->entries
[uid
]);
1201 usymtab_supReturnTypeEntry (/*@only@*/ uentry e
)
1202 /*@globals globtab, filetab@*/
1203 /*@modifies globtab@*/
1207 DPRINTF (("Abstract? %s", uentry_unparseFull (e
)));
1209 if (uentry_isAbstractDatatype (e
))
1211 uid
= typeId_toUsymId (usymtab_supAbstractTypeEntry (e
, FALSE
));
1213 else if (uentry_isMaybeAbstract (e
) && context_getFlag (FLG_IMPABSTRACT
))
1215 bool maybeabs
= TRUE
;
1216 cstring sname
= uentry_getName (e
);
1217 uentry ue
= usymtab_lookupGlobSafe (sname
);
1218 cstring_free (sname
);
1220 if (uentry_isValid (ue
))
1222 DPRINTF (("Lookup: %s", uentry_unparseFull (ue
)));
1224 if (uentry_isDatatype (ue
))
1226 if (uentry_isMaybeAbstract (ue
))
1237 DPRINTF (("Not datatype!"));
1244 typeId tid
= usymtab_supAbstractTypeEntry (e
, FALSE
);
1245 ux
= usymtab_getTypeEntry (tid
);
1246 uentry_setAbstract (ux
);
1247 uid
= typeId_toUsymId (tid
);
1251 uid
= usymtab_supEntryAux (globtab
, e
, FALSE
);
1252 e
= usymtab_getTypeEntry (typeId_fromUsymId (uid
));
1254 if (uentry_isMaybeAbstract (e
))
1256 uentry_setConcrete (e
);
1262 uid
= usymtab_supEntryAux (globtab
, e
, FALSE
);
1263 e
= usymtab_getTypeEntry (typeId_fromUsymId (uid
));
1265 /*? evans 2002-12-16 removed this? it doesn't make sense
1266 if (uentry_isMaybeAbstract (e))
1268 uentry_setConcrete (e);
1273 if (sRef_modInFunction ())
1275 recordFunctionType (globtab
->entries
[uid
]);
1278 return (globtab
->entries
[uid
]);
1282 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e
, bool dodef
)
1283 /*@globals globtab, filetab@*/
1284 /*@modifies globtab, e@*/
1289 uid
= typeId_fromUsymId (usymtab_supEntryAux (globtab
, e
, FALSE
));
1290 ue
= usymtab_getTypeEntry (uid
);
1294 uentry_setDatatype (ue
, uid
);
1297 if (context_getFlag (FLG_ACCESSMODULE
)) /* was accessfile */
1299 context_addFileAccessType (uid
);
1302 if (sRef_modInFunction ())
1304 recordFunctionType (globtab
->entries
[uid
]);
1311 usymtab_supExposedTypeEntry (/*@only@*/ uentry e
, bool dodef
)
1312 /*@globals globtab, filetab@*/
1313 /*@modifies globtab, e@*/
1317 uid
= typeId_fromUsymId (usymtab_supEntryAux (globtab
, e
, FALSE
));
1321 uentry ue
= usymtab_getTypeEntry (uid
);
1323 uentry_setDatatype (ue
, uid
);
1326 if (sRef_modInFunction ())
1328 recordFunctionType (globtab
->entries
[uid
]);
1335 usymtab_supForwardTypeEntry (/*@only@*/ uentry e
)
1336 /*@globals globtab, filetab@*/
1337 /*@modifies globtab, e@*/
1339 typeId uid
= typeId_fromUsymId (usymtab_supEntryAux (globtab
, e
, FALSE
));
1340 uentry ue
= usymtab_getTypeEntry (uid
);
1342 uentry_setDatatype (ue
, uid
);
1344 if (sRef_modInFunction ())
1346 recordFunctionType (globtab
->entries
[uid
]);
1349 return (uentry_getAbstractType (ue
));
1353 usymtab_supEntrySref (uentry e
)
1354 /*@globals utab, globtab, filetab@*/
1355 /*@modifies utab, globtab, e@*/
1357 sRef old
= uentry_getSref (e
);
1359 if (sRef_isType (old
))
1361 uentry ue
= usymtab_supEntryReturnAux (utab
, e
, TRUE
);
1364 if (uentry_isValid (ue
))
1366 sRef uref
= uentry_getSref (ue
);
1368 sRef_mergeStateQuiet (uref
, old
);
1369 sRef_clearDerived (uref
);
1371 /*@noaccess uentry@*/
1373 else if (sRef_isKnown (old
))
1375 usymtab_supEntry (e
);
1379 (void) usymtab_supEntryAux (utab
, e
, TRUE
);
1383 void usymtab_supGlobalEntry (/*@only@*/ uentry e
)
1384 /*@globals globtab, filetab@*/
1385 /*@modifies globtab, filetab, e@*/
1389 DPRINTF (("Sup global entry: %s", uentry_unparse (e
)));
1391 uid
= usymtab_supEntryAux (globtab
, e
, FALSE
);
1393 if (sRef_modInFunction ())
1395 recordFunctionType (globtab
->entries
[uid
]);
1400 usymtab_supReturnFileEntry (/*@only@*/ uentry e
)
1401 /*@globals filetab, globtab@*/
1402 /*@modifies filetab, globtab, e@*/
1404 llassert (filetab
!= usymtab_undefined
);
1405 DPRINTF (("File entry: %s", uentry_unparse (e
)));
1406 return (usymtab_supEntryReturnAux (filetab
, e
, FALSE
));
1414 usymtab_inDeepScope (void) /*@globals utab@*/
1416 return (utab
->lexlevel
> paramsScope
);
1420 usymtab_getIndex (/*@notnull@*/ usymtab s
, cstring k
)
1424 DPRINTF (("Lookup %s", k
));
1426 if (cstringTable_isDefined (s
->htable
))
1428 i
= cstringTable_lookup (s
->htable
, k
);
1429 return usymId_fromInt (i
);
1433 for (i
= 0; i
< s
->nentries
; i
++)
1435 uentry current
= s
->entries
[i
];
1437 DPRINTF (("Check %d: %s", i
, uentry_rawName (current
)));
1439 if (!uentry_isUndefined (current
)
1440 && cstring_equal (uentry_rawName (current
), k
))
1442 return usymId_fromInt (i
);
1446 return usymId_notfound
;
1451 usymtab_fetchIndex (/*@notnull@*/ usymtab s
, usymId ui
)
1453 int i
= usymId_toInt (ui
);
1454 llassert (i
>= 0 && i
< s
->nentries
);
1455 return (s
->entries
[i
]);
1459 usymtab_getTypeId (cstring k
) /*@globals globtab@*/
1461 usymId uid
= usymtab_getIndex (globtab
, k
);
1463 if (!usymtab_indexFound (uid
)
1464 || !(uentry_isDatatype (usymtab_getTypeEntry (typeId_fromUsymId (uid
)))))
1467 return typeId_invalid
;
1471 return typeId_fromUsymId (uid
);
1475 /*@dependent@*/ uentry
1476 usymtab_lookupStructTag (cstring k
)
1478 cstring sname
= makeStruct (k
);
1479 uentry ue
= usymtab_lookupGlob (sname
);
1481 cstring_free (sname
);
1485 /*@dependent@*/ uentry
1486 usymtab_lookupUnionTag (cstring k
)
1488 cstring uname
= makeUnion (k
);
1489 uentry res
= usymtab_lookupGlob (uname
);
1491 cstring_free (uname
);
1495 /*@dependent@*/ uentry
1496 usymtab_lookupEnumTag (cstring k
)
1498 cstring ename
= makeEnum (k
);
1499 uentry res
= usymtab_lookupGlob (ename
);
1501 cstring_free (ename
);
1506 usymtab_getId (cstring k
) /*@globals globtab@*/
1508 usymId uid
= usymtab_getIndex (globtab
, k
);
1511 if (!usymtab_indexFound (uid
))
1513 return usymId_invalid
;
1516 ue
= usymtab_getGlobalEntry (uid
);
1518 if (uentry_isPriv (ue
))
1520 return usymId_invalid
;
1526 static /*@exposed@*/ uentry
1527 usymtab_getEntryAux (/*@notnull@*/ usymtab s
, usymId uid
)
1529 llassert (uid
!= usymId_invalid
);
1531 if (uid
< 0 || uid
>= usymId_fromInt (s
->nentries
))
1533 llcontbug (message ("%s: out of range: level = %d [%d]",
1534 cstring_fromChars (__func__
), s
->lexlevel
, uid
));
1535 return uentry_undefined
;
1538 llassertprint (uentry_isValid (s
->entries
[uid
]),
1539 ("entry undefined: %d", uid
));
1541 return s
->entries
[uid
];
1544 /*@dependent@*/ /*@observer@*/ uentry
1545 usymtab_getGlobalEntry (usymId uid
)
1546 /*@globals utab, globtab@*/
1548 if (dbgfree
) return (uentry_undefined
);
1550 if (utab
->lexlevel
> paramsScope
)
1552 /* need to do this the awkward way, since it could be in conditional scope */
1553 return (usymtab_lookupSafe (uentry_rawName (globtab
->entries
[uid
])));
1557 return (globtab
->entries
[uid
]);
1561 /*@dependent@*/ /*@exposed@*/ uentry
usymtab_getTypeEntry (typeId uid
)
1562 /*@globals globtab@*/
1566 if (uid
>= 0 && uid
< typeId_fromInt (globtab
->nentries
))
1568 return (globtab
->entries
[uid
]);
1572 return (uentry_undefined
);
1577 llassert (uid
>= 0 && uid
< typeId_fromInt (globtab
->nentries
));
1578 return (globtab
->entries
[uid
]);
1586 /*@dependent@*/ /*@exposed@*/ uentry
usymtab_getTypeEntrySafe (typeId uid
)
1587 /*@globals globtab@*/
1589 if (uid
< 0 || uid
>= typeId_fromInt (globtab
->nentries
))
1591 return uentry_undefined
;
1594 return (globtab
->entries
[uid
]);
1597 bool usymtab_isBoolType (typeId uid
)
1598 /*@globals globtab@*/
1600 llassert (uid
>= 0 && uid
< typeId_fromInt (globtab
->nentries
));
1602 return (cstring_equal (uentry_rawName (globtab
->entries
[uid
]),
1603 context_getBoolName ()));
1606 cstring
usymtab_getTypeEntryName (typeId uid
)
1607 /*@globals globtab@*/
1613 return (cstring_makeLiteral ("<freetype>"));
1616 ue
= usymtab_getTypeEntry (uid
);
1618 if (dbgload
&& !uentry_isValid (ue
))
1620 return (message ("<missing type: %d>", uid
));
1623 llassertprint (uentry_isValid (ue
), ("type undefined: %d", uid
));
1625 return (uentry_getName (ue
));
1629 /*@unused@*/ static void
1630 usymtab_rehash (/*@notnull@*/ usymtab s
)
1634 if (cstringTable_isDefined (s
->htable
))
1636 cstringTable_free (s
->htable
);
1639 s
->htable
= cstringTable_create (LLAHSHSIZE
);
1641 for (i
= 0; i
< s
->nentries
; i
++)
1643 cstringTable_insert (s
->htable
, cstring_copy (uentry_rawName (s
->entries
[i
])), i
);
1649 ** superficial copy of usymtab
1651 ** DO copy spec entries
1654 static /*@only@*/ /*@notnull@*/ usymtab
1655 usymtab_shallowCopy (/*@notnull@*/ usymtab s
) /*@*/
1657 usymtab copytab
= usymtab_createRoot ();
1660 for (i
= 0; i
< s
->nentries
; i
++)
1662 usymtab_addEntryBase (copytab
, s
->entries
[i
]);
1669 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s
)
1671 aliasTable_free (s
->aliases
);
1672 refTable_free (s
->reftable
, s
->nentries
);
1674 /*@-compdestroy@*/ sfree (s
); /*@=compdestroy@*/
1677 usymId
usymtab_convertTypeId (typeId uid
)
1679 return usymtab_convertId (typeId_toUsymId (uid
));
1683 ** usymtab_convertId: converts usymId from old table to sorted one
1686 usymId
usymtab_convertId (usymId uid
)
1687 /*@globals oldtab, utab@*/
1693 llassert (usymtab_isDefined (oldtab
));
1695 ue
= usymtab_getEntryAux (oldtab
, uid
);
1697 llassertprint (uentry_isValid (ue
), ("convertId: undefined: %d", uid
));
1699 name
= uentry_rawName (ue
);
1701 ret
= usymtab_getIndex (utab
, name
);
1702 llassert (ret
== uid
); /*! for now, no rehash! */
1703 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1704 uentry_unparse (ue
), uid
,
1705 uentry_unparse (utab
->entries
[ret
]), ret
));
1707 llassertprint (ret
!= usymId_invalid
, ("convertId: return is invalid"));
1713 usymtab_prepareDump (void)
1714 /*@globals oldtab, utab@*/
1715 /*@modifies oldtab, utab@*/
1717 llassert (usymtab_inGlobalScope ());
1718 llassert (oldtab
== usymtab_undefined
);
1721 DPRINTF (("Preparing to dump:"));
1722 usymtab_printAll ();
1725 oldtab
= usymtab_shallowCopy (utab
);
1729 ** alpha compare - make sure order is same on different platforms
1730 ** error messages appear in same order
1733 qsort (utab
->entries
, (size_t)utab
->nentries
,
1734 sizeof (*utab
->entries
),
1735 (int (*)(const void *, const void *)) uentry_xcomparealpha
);
1737 usymtab_rehash (utab
);
1741 DPRINTF (("After rehash:"));
1742 usymtab_printAll ();
1746 void usymtab_dump (FILE *fout
)
1747 /*@globals utab, oldtab@*/
1750 bool neednl
= FALSE
;
1751 uentry lastentry
= uentry_undefined
;
1752 ekind lastekind
= KINVALID
;
1756 ** must call prepareDump first
1759 llassert (oldtab
!= usymtab_undefined
);
1761 for (i
= 0; i
< utab
->nentries
; i
++)
1763 uentry thisentry
= utab
->entries
[i
];
1764 ekind thisekind
= uentry_getKind (thisentry
);
1766 if (!uentry_hasRealName (thisentry
))
1768 llassert (uentry_isGlobalMarker (thisentry
));
1772 check (fputc ('\n', fout
) == (int) '\n');
1775 fprintf (fout
, "*%d (GlobalMarker)\n", KGLOBALMARKER
);
1776 lastekind
= KINVALID
;
1782 if (thisekind
!= lastekind
)
1786 check (fputc ('\n', fout
) == (int) '\n');
1790 lastentry
= uentry_undefined
;
1791 fprintf (fout
, "*%d (%s)\n", ekind_toInt (thisekind
),
1792 cstring_toCharsSafe (ekind_capName (thisekind
)));
1793 lastekind
= thisekind
;
1798 ** evans - 2001-02-18 - added the - 48 fudge factor...
1799 ** extra characters dumped, but I haven't counded them carefully...
1802 if (uentry_isInvalid (lastentry
) || !uentry_equiv (lastentry
, thisentry
)
1803 || (linelen
> (MAX_DUMP_LINE_LENGTH
- (2 * MAX_NAME_LENGTH
) - 48)))
1807 DPRINTF (("Dumping entry: %d", i
));
1808 cdump
= message ("^%d %q", i
, uentry_dump (thisentry
));
1809 /* was: cdump = uentry_dump (thisentry)); */
1811 lastentry
= thisentry
;
1814 check (fputc ('\n', fout
) == (int) '\n');
1818 linelen
+= cstring_length (cdump
);
1820 /* no new line here! */
1821 if (cstring_length (cdump
) > 0)
1823 check (fputs (cstring_toCharsSafe (cdump
), fout
) != EOF
);
1826 cstring_free (cdump
);
1831 cstring cdump
= uentry_rawName (thisentry
);
1832 DPRINTF (("Raw name: %s", cdump
));
1833 linelen
+= (cstring_length (cdump
) + 1);
1834 fprintf (fout
, "#%s", cstring_toCharsSafe (cdump
));
1841 check (fputc ('\n', fout
) == (int) '\n');
1844 lastekind
= KINVALID
;
1846 fprintf(fout
, ";; Library constraints\n");
1848 /*drl July 27 added this so that libraries without
1849 buffer constraints would be handled correctly.
1850 I'm trying to do this without breaking older libraries.
1852 Splint should still be able to handle libraries without this message.
1856 fprintf(fout
, "start_Buffer_Constraints\n");
1858 for (i
= 0; i
< utab
->nentries
; i
++)
1860 uentry thisentry
= utab
->entries
[i
];
1862 if (uentry_isFunction (thisentry
) )
1864 constraintList preconditions
;
1865 constraintList postconditions
;
1867 preconditions
= uentry_getFcnPreconditions (thisentry
);
1868 postconditions
= uentry_getFcnPostconditions (thisentry
);
1870 if ( constraintList_isDefined(preconditions
) ||
1871 constraintList_isDefined(postconditions
) )
1873 fprintf(fout
,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry
) ) );
1874 if (constraintList_isDefined(preconditions
) )
1876 fprintf(fout
,"pre:\n");
1877 constraintList_dump(preconditions
, fout
);
1878 fprintf (fout
, ";; end precondition constraints\n" );
1879 constraintList_free(preconditions
);
1883 fprintf(fout
,"pre:EMPTY\n");
1885 if (constraintList_isDefined(postconditions
) )
1887 fprintf(fout
,"post:\n");
1888 constraintList_dump(postconditions
, fout
);
1889 fprintf (fout
, ";; end precondition constraints\n" );
1890 constraintList_free(postconditions
);
1894 fprintf(fout
,"post:EMPTY\n");
1903 void usymtab_load (FILE *f
)
1904 /*@globals utab, globtab@*/
1905 /*@modifies utab, *f@*/
1907 char *s
= mstring_create (MAX_DUMP_LINE_LENGTH
);
1909 ekind kind
= KINVALID
;
1910 fileloc loc
= g_currentloc
;
1916 llassert (utab
== globtab
);
1917 llassert (utab
->nentries
== 0);
1919 while (((s
= reader_readLine (f
, s
, MAX_DUMP_LINE_LENGTH
)) != NULL
)
1922 /* ignore ; comments */ ;
1925 while (s
!= NULL
&& *s
!= ';')
1933 ek
= reader_getInt (&s
);
1935 if (ek
== KGLOBALMARKER
)
1937 uentry lue
= uentry_makeGlobalMarker ();
1938 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue
)));
1939 usymtab_addEntryAlways (utab
, lue
);
1945 kind
= ekind_fromInt (ek
);
1953 (cstring_makeLiteral
1954 ("Library is in obsolete format. Use splint +whichlib "
1955 "to see which library is being loaded."));
1958 if (reader_optCheckChar (&s
, '^'))
1960 index
= reader_getInt (&s
);
1967 llassert (kind
!= KINVALID
);
1968 ue
= uentry_undump (kind
, loc
, &s
);
1970 llassert (utab
->nentries
== index
|| index
== -1);
1972 if (uentry_isValid (ue
))
1974 int lastindex
= utab
->nentries
;
1975 ue
= usymtab_addEntryAlways (utab
, ue
);
1979 if (uentry_isConstant (ue
)) /*@i23! isPreProcessorMacro */
1981 cstring uname
= uentry_getName (ue
);
1983 /* Also check its a macro... */
1984 DPRINTF (("Installing: %s", uname
));
1986 cpphash_installMacro
1987 (mstring_copy (cstring_toCharsSafe (uname
)),
1988 cstring_length (uname
),
1989 cpplib_createDefinition (message ("%s 255", uname
),
1992 cpphash_hashCode (cstring_toCharsSafe (uname
),
1993 cstring_length (uname
),
1996 DPRINTF (("After install: %s", uname
));
2000 if (utab
->nentries
!= lastindex
+ 1)
2002 DPRINTF (("No add: %s", uentry_unparseFull (ue
)));
2010 ** now, any other names are the same uentry
2013 while (*(s
++) == '#')
2015 cstring name
= cstring_fromCharsO (reader_getWord (&s
));
2016 uentry nue
= uentry_nameCopy (name
, ue
);
2018 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
2022 usymtab_addEntryAlways (utab
, nue
);
2025 while ((c
= *s
) != '\0' && (c
!='\n'))
2027 if (!(c
== ' ' || c
== '\t'))
2029 llbuglit ("Junk in load file");
2037 s
= reader_readLine (f
, os
, MAX_DUMP_LINE_LENGTH
);
2042 to handle reading of buffer overflow related constraints
2044 while (fgets (s
, MAX_DUMP_LINE_LENGTH
, f
) != NULL
2047 ; /* ignore ;-comments */
2050 /*drl July 27 added this so that libraries without
2051 buffer constraints would be handled correctly.
2052 I'm trying to do this without breaking older libraries*/
2054 /*check for "optional" start buffer constraints message*/
2056 if (mstring_equalPrefix (s
, "start_Buffer_Constraints"))
2058 (void) fgets (s
, MAX_DUMP_LINE_LENGTH
, f
);
2061 while (s
!= NULL
&& *s
!= ';')
2063 constraintList preconditions
;
2064 constraintList postconditions
;
2065 cstring name
= cstring_fromChars (reader_getWord (&s
));
2068 ue
= usymtab_lookup (name
);
2069 cstring_free (name
);
2071 preconditions
= constraintList_undefined
;
2072 postconditions
= constraintList_undefined
;
2074 if (!uentry_isValid(ue
) )
2076 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s
) ) ));
2078 s
= fgets (os
, MAX_DUMP_LINE_LENGTH
, f
);
2080 temp
= cstring_fromChars (reader_getWord(&s
) );
2082 if (cstring_compareLit (temp
,"pre:") == 0 )
2084 preconditions
= constraintList_undump (f
);
2088 if (cstring_compareLit (temp
,"pre:EMPTY") != 0 )
2089 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp
) ));
2094 s
= fgets (os
, MAX_DUMP_LINE_LENGTH
, f
);
2096 temp
= cstring_fromChars(reader_getWord(&s
) );
2097 if (cstring_compareLit (temp
, "post:") == 0 )
2099 postconditions
= constraintList_undump (f
);
2103 if (cstring_compareLit (temp
, "post:EMPTY") != 0 )
2104 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp
) ));
2107 cstring_free (temp
);
2109 uentry_setPreconditions (ue
, functionConstraint_createBufferConstraint (preconditions
));
2110 uentry_setPostconditions (ue
, functionConstraint_createBufferConstraint (postconditions
));
2112 s
= fgets (os
, MAX_DUMP_LINE_LENGTH
, f
);
2120 ** file scope for static variables
2124 usymtab_enterFile (void)
2125 /*@globals utab, globtab, filetab@*/
2126 /*@modifies filetab@*/
2128 llassert (utab
== globtab
);
2133 usymtab_entries (globtab
, ue
)
2135 if (sRef_hasDerived (uentry_getSref (ue
)))
2137 fprintf (g_warningstream
, "Derived Global: %s\n", uentry_unparse (ue
));
2138 fprintf (g_warningstream
, "sRef: %s\n", sRef_unparseFull (ue
->sref
));
2140 } end_usymtab_entries
;
2144 usymtab_enterScope ();
2149 usymtab_exitFile (void)
2150 /*@globals utab, filetab@*/
2151 /*@modifies filetab, utab@*/
2154 llassert (utab
->lexlevel
== 1);
2156 usymtab_exitScope (exprNode_undefined
);
2161 usymtab_enterScope (void)
2162 /*@globals utab, globtab, filetab@*/
2165 usymtab t
= usymtab_create (US_NORMAL
, utab
, TRUE
);
2167 /* unconditional scope: optimize to avoid copy */
2168 t
->aliases
= aliasTable_copy (utab
->aliases
);
2171 llassert (usymtab_isDefined (t
->env
));
2173 if (t
->env
->lexlevel
== paramsScope
&& context_inFunctionLike ())
2175 noshadowerror
= TRUE
;
2176 usymtab_handleParams ();
2177 noshadowerror
= FALSE
;
2182 ** setup external references:
2183 ** o only, unique params alias external args
2184 ** o other params may alias anything of their type
2188 usymtab_handleParams (void)
2189 /*@globals utab, globtab, filetab@*/
2190 /*@modifies utab, globtab@*/
2192 usymtab ptab
= utab
->env
;
2193 uentry fcn
= context_getHeader ();
2195 usymtab_entries (ptab
, param
)
2199 if (!uentry_isYield (param
))
2202 sRef pref
= uentry_getSref (param
);
2204 /* Could be a global. */
2206 if (uentry_isAnyParam (param
))
2208 ue
= uentry_makeVariable (fixParamName (uentry_rawName (param
)),
2209 uentry_getType (param
),
2210 fileloc_copy (uentry_whereDeclared (param
)),
2213 uentry_copyState (ue
, param
);
2214 uentry_setRefParam (ue
);
2216 ue
= usymtab_supEntrySrefReturn (ue
);
2218 /* must be after supercede! */
2220 if (!sRef_stateKnown (pref
))
2222 uentry_setDefState (ue
, SS_DEFINED
);
2223 uentry_setDefState (param
, SS_DEFINED
);
2227 if (sRef_isStateSpecial (pref
))
2229 uentry_setDefState (ue
, SS_SPECIAL
); /* ALLOCATED); */
2230 /* evans 2002-01-01: should be unnecessary, the pre clauses
2231 ** set the state if necessary.
2236 uentry_setDefState (ue
, sRef_getDefState (pref
));
2240 uref
= uentry_getSref (ue
);
2242 if (sRef_isStack (uref
))
2244 alkind pkind
= sRef_getAliasKind (pref
);
2246 if (alkind_isKnown (pkind
) && !alkind_isLocal (pkind
)
2247 && !alkind_isStack (pkind
))
2249 sRef_setAliasKind (uref
, pkind
, fileloc_undefined
);
2250 sRef_setOrigAliasKind (uref
, pkind
);
2254 sRef_setAliasKind (uref
, AK_IMPTEMP
, fileloc_undefined
);
2255 sRef_setOrigAliasKind (uref
, AK_IMPTEMP
);
2257 if (uentry_isOut (param
))
2263 sRef_setDefined (uref
, fileloc_undefined
);
2269 usymtab_addMustAlias (uref
, pref
);
2271 if (!(uentry_isOnly (param
) || uentry_isUnique (param
)))
2274 ** This is needed for detecting possibly aliased parameters.
2277 sRef s
= sRef_makeExternal (uref
);
2278 usymtab_addMustAlias (uref
, s
);
2281 if (sRef_isKillRef (pref
))
2283 sRef_setAliasKind (uref
, AK_NEWREF
, fileloc_undefined
);
2284 sRef_setOrigAliasKind (uref
, AK_KILLREF
);
2286 else if (sRef_isRefCounted (uref
))
2288 sRef_setOrigAliasKind (uref
, AK_REFCOUNTED
);
2293 sRef_setOrigAliasKind (uref
, AK_LOCAL
);
2300 } end_usymtab_entries
;
2303 if (uentry_hasStateClauseList (fcn
))
2305 stateClauseList clauses
= uentry_getStateClauseList (fcn
);
2307 stateClauseList_preElements (clauses
, cl
)
2309 fileloc loc
= stateClause_loc (cl
);
2312 if (stateClause_isGlobal (cl
))
2314 DPRINTF (("Global Marker: %s",
2315 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2316 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2317 srs
= sRefSet_single (usymtab_lookupGlobalMarker ());
2321 srs
= stateClause_getRefs (cl
);
2324 sRefSet_elements (srs
, el
)
2326 sRef base
= sRef_getRootBase (el
);
2327 sRef sb
= sRef_updateSref (el
);
2329 if (sRef_isResult (base
))
2331 ; /* nothing to do before */
2333 else if (sRef_isParam (base
) || sRef_isGlobalMarker (base
))
2335 if (stateClause_setsMetaState (cl
))
2337 /* copied from exprNode.c:3040 */
2338 qual ql
= stateClause_getMetaQual (cl
);
2339 annotationInfo ainfo
= qual_getAnnotationInfo (ql
);
2340 metaStateInfo minfo
= annotationInfo_getState (ainfo
);
2341 cstring key
= metaStateInfo_getName (minfo
);
2342 int mvalue
= annotationInfo_getValue (ainfo
);
2344 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl
)));
2346 if (sRef_isResult (base
))
2352 sRef_setMetaStateValueComplete (sb
, key
, mvalue
, loc
);
2357 sRefMod modf
= stateClause_getEntryFunction (cl
);
2361 sRefSet aliases
= usymtab_allAliases (sb
);
2365 sRefSet_elements (aliases
, sr
)
2368 } end_sRefSet_elements
;
2370 sRefSet_free (aliases
);
2376 if (sRef_isValid (base
))
2378 DPRINTF (("Base: %s", sRef_unparseFull (base
)));
2382 } end_sRefSet_elements
;
2383 } end_stateClauseList_preElements
;
2388 usymtab_enterFunctionScope (uentry fcn
)
2389 /*@globals utab, filetab, globtab@*/
2392 usymtab t
= usymtab_create (US_NORMAL
, utab
, TRUE
);
2394 DPRINTF (("Enter function: %s", uentry_unparse (fcn
)));
2396 if (utab
->lexlevel
!= fileScope
)
2398 if (utab
->lexlevel
> fileScope
)
2400 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2402 while (utab
->lexlevel
> fileScope
)
2404 /*@i@*/ utab
= usymtab_dropEnv (utab
);
2411 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2413 /*@-branchstate@*/ } /*@=branchstate@*/
2417 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn
))));
2419 globSet_allElements (uentry_getGlobs (fcn
), el
)
2421 DPRINTF (("Here we go: %s", sRef_unparseFull (el
)));
2423 if (sRef_isUndefGlob (el
))
2425 usymId index
= sRef_getScopeIndex (el
);
2426 sRef sr
= sRef_updateSref (el
);
2427 fileloc loc
= uentry_whereEarliest (fcn
);
2429 DPRINTF (("update: %s", sRef_unparseFull (sr
)));
2430 DPRINTF (("Undef!"));
2431 if (sRef_isFileStatic (el
))
2433 ctype ct
= sRef_getType (el
);
2435 if (ctype_isRealArray (ct
) || ctype_isRealSU (ct
))
2437 sRef_setAllocated (sr
, loc
);
2441 sRef_setUndefined (sr
, loc
);
2446 uentry ue
= globtab
->entries
[index
];
2447 ctype ct
= uentry_getType (ue
);
2449 if (ctype_isArray (ct
) || ctype_isSU (ct
))
2451 sRef_setAllocated (sr
, loc
);
2455 sRef_setUndefined (sr
, loc
);
2459 else if (sRef_isAllocated (el
))
2461 sRef sr
= sRef_updateSref (el
);
2462 fileloc loc
= uentry_whereEarliest (fcn
);
2464 sRef_setAllocated (sr
, loc
);
2466 else if (sRef_isPartial (el
))
2468 sRef sr
= sRef_updateSref (el
);
2469 fileloc loc
= uentry_whereEarliest (fcn
);
2471 sRef_setPartial (sr
, loc
);
2476 sRef sr = sRef_updateSref (el);
2477 fileloc loc = uentry_whereEarliest (fcn);
2479 sRef_setDefined (sr, loc);
2483 /* shouldn't need to do anything! */
2485 } end_globSet_allElements
;
2487 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn
))));
2489 usymtab_checkAllValid ();
2494 usymtab_caseBranch (void)
2497 usymtab t
= usymtab_create (US_CBRANCH
, utab
, FALSE
);
2502 usymtab_switchBranch (/*@unused@*/ exprNode s
)
2505 usymtab t
= usymtab_create (US_SWITCH
, utab
, FALSE
);
2507 t
->aliases
= aliasTable_copy (utab
->aliases
);
2512 usymtab_trueBranch (/*@only@*/ guardSet guards
)
2515 usymtab t
= usymtab_create (US_TBRANCH
, utab
, FALSE
);
2518 ** not true! (could be in a macro)
2520 ** llassertprint (utab->lexlevel > paramsScope,
2521 ** ("not in scope: %s", usymtab_unparseLocal ()));
2525 guardSet_free (t
->guards
);
2528 aliasTable_free (t
->aliases
);
2529 t
->aliases
= aliasTable_copy (utab
->aliases
);
2537 ** { int a; if (...) a = 3; < a may be undefined here!
2542 usymtab_popTrueBranch (exprNode pred
, exprNode expr
, clause cl
) /*@modifies utab@*/
2545 ** add a false branch
2546 ** (could be done more efficiently as a special case, but
2547 ** it is better to only maintain one version of the code)
2550 if (utab
->kind
!= US_TBRANCH
2551 && context_inIterDef ())
2553 usymtab_exitScope (expr
);
2557 DPRINTF (("pop true branch.."));
2558 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred
)));
2559 usymtab_popBranches (pred
, expr
, exprNode_undefined
, TRUE
, cl
);
2564 usymtab_popCaseBranch (void) /*@modifies utab@*/
2566 llassert (utab
->kind
== US_CBRANCH
);
2567 usymtab_quietPlainExitScope ();
2571 usymtab_popTrueExecBranch (exprNode pred
, exprNode expr
, clause cl
)
2574 ** add a false branch that must return --- that is,
2575 ** the true branch is always executed!
2578 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred
)));
2579 usymtab_popBranches (pred
, expr
, exprNode_makeMustExit (), FALSE
, cl
);
2583 usymtab_popOrBranch (exprNode pred
, exprNode expr
)
2587 usymtab env
= utab
->env
;
2588 usymtab otab
= utab
;
2591 llassert (env
!= NULL
);
2593 if (exprNode_isError (expr
))
2599 mustReturn
= exprNode_mustEscape (expr
);
2603 llassert (utab
->kind
== US_TBRANCH
);
2606 ** merge each entry in table with its original
2607 ** unless execution cannot continue after this branch
2610 for (i
= 0; i
< utab
->nentries
; i
++)
2612 uentry current
= utab
->entries
[i
];
2613 uentry old
= usymtab_lookupAux (env
, uentry_rawName (current
));
2615 uentry_mergeState (old
, current
, exprNode_loc (expr
),
2616 mustReturn
, FALSE
, TRUE
, ORCLAUSE
);
2622 env
->guards
= guardSet_levelUnionFree (env
->guards
,
2623 guardSet_invert (exprNode_getGuards (pred
)),
2628 env
->aliases
= aliasTable_levelUnion (env
->aliases
, otab
->aliases
, env
->lexlevel
);
2631 /* env is now utab */
2632 usymtab_quietPlainExitScope ();
2636 ** case syntax in C is very unrestricted. This is unfortunate.
2638 ** A switch case is ended either by a new case or default, or
2639 ** a close } that may close the switch or some other control
2644 usymtab_newCase (/*@unused@*/ exprNode pred
, exprNode last
)
2647 bool mustBreak
= usymtab_mustBreak (utab
);
2648 bool mustReturn
= usymtab_mustEscape (utab
);
2649 usymtab stab
= utab
;
2651 DPRINTF (("New case!"));
2654 ** Find last case (or outer switch)
2657 while (stab
->kind
!= US_CBRANCH
&& stab
->kind
!= US_SWITCH
)
2660 llassert (stab
!= GLOBAL_ENV
);
2663 while (stab
->kind
== US_CBRANCH
)
2666 llassert (stab
!= GLOBAL_ENV
);
2670 ** if its a fall through case, merge in outside entries and last case.
2675 ** case 1: x = 3; <fall through>
2676 ** case 2: << x may not be defined
2680 if (!mustBreak
&& !mustReturn
&& utab
->kind
== US_CBRANCH
)
2682 llassert (stab
->kind
== US_SWITCH
|| stab
->kind
== US_NORMAL
);
2684 usymtab_entries (utab
, ue
) /* but, keep track of used variables */
2686 uentry old
= usymtab_lookupAux (stab
, uentry_rawName (ue
));
2688 llassert (uentry_isValid (old
));
2690 /* modifies ue, not old */
2692 uentry_mergeState (ue
, old
, exprNode_loc (last
),
2693 FALSE
, FALSE
, TRUE
, CASECLAUSE
);
2694 } end_usymtab_entries
;
2696 utab
->aliases
= aliasTable_levelUnion (utab
->aliases
,
2697 stab
->aliases
, utab
->lexlevel
);
2700 ** No need for a new branch.
2707 usymtab_caseBranch ();
2708 /*@-mustfree@*/ /*< utab->aliases >*/
2709 utab
->aliases
= aliasTable_copy (stab
->aliases
);
2717 ** for && (both pred and expr are executed)
2721 usymtab_popAndBranch (exprNode pred
, /*@unused@*/ exprNode expr
)
2724 usymtab env
= utab
->env
;
2728 llassert (utab
->kind
== US_TBRANCH
);
2731 ** merge each entry in table with its original
2732 ** unless execution cannot continue after this branch
2735 for (i
= 0; i
< utab
->nentries
; i
++)
2737 uentry current
= utab
->entries
[i
];
2738 sRef tref
= uentry_getSref (current
);
2739 uentry old
= usymtab_lookupAux (env
, uentry_rawName (current
));
2740 sRef oref
= uentry_getSref (old
);
2742 /* note that is current is in a nested branch,
2743 it may create a "new" old entry. */
2745 llassert (uentry_isValid (old
));
2746 uentry_mergeState (old
, current
, exprNode_loc (expr
),
2747 FALSE
, FALSE
, TRUE
, ANDCLAUSE
);
2750 ** if is it defined by the second clause, then it should be defined.
2753 if (sRef_isAnyDefined (tref
)
2754 && (sRef_isAllocated (oref
) || sRef_isStateUndefined (oref
)))
2756 sRef_setDefined (oref
, g_currentloc
);
2760 DPRINTF (("Popping and: %s / %s",
2761 guardSet_unparse (utab
->guards
),
2762 guardSet_unparse (exprNode_getGuards (pred
))));
2764 utab
->guards
= guardSet_levelUnionFree (utab
->guards
,
2765 guardSet_invert (exprNode_getGuards (pred
)),
2767 utab
->aliases
= aliasTable_levelUnion (utab
->aliases
, otab
->aliases
, utab
->lexlevel
);
2769 usymtab_quietPlainExitScope ();
2774 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2775 ** Only branches which do not return (except possibly the last branch) are included.
2777 ** Conditionally merge state from all CBRANCHes.
2779 ** If allpaths is TRUE, then all possible executions go through some switch
2780 ** case, and the original scope is not merged.
2784 usymtab_exitSwitch (/*@unused@*/ exprNode sw
, bool allpaths
)
2787 usymtab ttab
= utab
;
2788 usymtab stab
= ttab
;
2789 usymtab ltab
= ttab
;
2790 bool lastMustReturn
= usymtab_mustEscape (utab
);
2794 while (stab
->kind
== US_CBRANCH
)
2797 llassert (stab
!= GLOBAL_ENV
);
2800 while (stab
->kind
== US_NORMAL
)
2803 llassert (stab
!= GLOBAL_ENV
);
2806 llassert (stab
->kind
== US_SWITCH
);
2808 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2810 llassert (stab
!= GLOBAL_ENV
);
2814 llassert (usymtab_isDefined (ttab
));
2816 if (ttab
->kind
== US_CBRANCH
)
2818 /* was quietPlainExitScope --- but, can't free it yet! */
2820 llassert (utab
!= GLOBAL_ENV
);
2822 while (ttab
->kind
== US_CBRANCH
)
2825 ** (from popTrueBranch)
2828 bool mustReturn
= usymtab_mustEscape (ttab
);
2829 bool mustBreak
= usymtab_mustBreak (ttab
);
2831 usymtab_entries (ttab
, current
)
2833 uentry old
= /*@-compmempass@*/ usymtab_lookupAux (ltab
, uentry_rawName (current
));
2837 ** note that is this is in a nested branch,
2838 ** it may create a "new" old entry.
2841 if (uentry_isValid (old
))
2845 uentry_mergeUses (current
, old
);
2846 uentry_setState (old
, current
);
2850 uentry_mergeState (old
, current
, exprNode_loc (sw
),
2851 mustReturn
, FALSE
, TRUE
, SWITCHCLAUSE
);
2858 } end_usymtab_entries
;
2861 ** if entry is not in symbol table for this case, merge with pre-switch
2865 if (!mustReturn
&& !mustBreak
)
2867 usymtab_entries (stab
, current
)
2869 if (!usymtab_indexFound (usymtab_getIndex (ttab
, uentry_rawName (current
))))
2871 uentry old
= /*@-compmempass@*/
2872 usymtab_lookupAux (ltab
, uentry_rawName (current
));
2875 llassert (uentry_isValid (old
));
2876 uentry_mergeState (old
, current
, exprNode_loc (sw
),
2877 FALSE
, FALSE
, TRUE
, SWITCHCLAUSE
);
2879 } end_usymtab_entries
;
2882 ltab
->env
= ttab
->env
;
2886 ** Suprious error, becuase of environments.
2889 /*@i1@*/ utab
= ltab
;
2891 lastMustReturn
= FALSE
;
2898 ** now, there is one US_CBRANCH. Merge this with the stab.
2902 for (i
= 0; i
< ltab
->nentries
; i
++)
2904 uentry current
= ltab
->entries
[i
];
2905 uentry old
= usymtab_lookupAux (stab
, uentry_rawName (current
));
2907 /* note that is this is in a nested branch,
2908 it may create a "new" old entry. */
2911 if (uentry_isValid (old
))
2915 uentry_mergeUses (current
, old
);
2916 uentry_setState (old
, current
);
2920 uentry_mergeState (old
, current
, exprNode_loc (sw
),
2921 FALSE
, FALSE
, TRUE
, SWITCHCLAUSE
);
2935 ** switch may or may not be followed by a new scope
2938 if (utab
->kind
== US_SWITCH
)
2940 usymtab_quietPlainExitScope ();
2944 usymtab_quietPlainExitScope ();
2945 llassert (utab
->kind
== US_SWITCH
);
2946 usymtab_quietPlainExitScope ();
2952 updateNullState (sRef el
, /*@notnull@*/ usymtab ttab
,
2953 /*@notnull@*/ usymtab ftab
, bool trueGuard
)
2955 sRef base
= sRef_getRootBase (el
);
2956 int level
= sRef_lexLevel (base
);
2958 if (sRef_isCvar (base
))
2960 usymId index
= sRef_getScopeIndex (base
);
2961 uentry ue
= usymtab_getRefTab (ttab
, level
, index
);
2963 if (!uentry_isLset (ue
))
2965 sRef sr
= uentry_getSref (ue
);
2969 sRef_setDerivNullState (sr
, el
, NS_NOTNULL
);
2973 if (!guardSet_isGuarded (ttab
->guards
, el
)
2974 && !sRef_isNotNull (sr
))
2976 DPRINTF (("Here! %s / %s",
2977 sRef_unparseFull (sr
),
2978 sRef_unparseFull (el
)));
2979 sRef_setDerivNullState (sr
, el
, NS_DEFNULL
);
2988 ue
= usymtab_getRefTab (ftab
, level
, index
);
2990 if (!uentry_isLset (ue
))
2992 sRef sr
= uentry_getSref (ue
);
2994 if (!trueGuard
) /* yikes! forgot the ! */
2996 sRef_setDerivNullState (sr
, el
, NS_NOTNULL
);
3001 if (!guardSet_isGuarded (ftab
->guards
, el
)
3002 && !sRef_isNotNull (sr
))
3004 sRef_setDerivNullState (sr
, el
, NS_DEFNULL
);
3016 usymtab_popBranches (exprNode pred
, exprNode tbranch
, exprNode fbranch
,
3017 bool isOpt
, clause cl
)
3021 usymtab ftab
= utab
;
3022 usymtab ttab
= utab
->env
;
3026 guardSet guards
= exprNode_getGuards (pred
);
3027 sRefSet tguards
= guardSet_getTrueGuards (guards
);
3028 sRefSet fguards
= guardSet_getFalseGuards (guards
);
3029 bool mustReturnT
= exprNode_mustEscape (tbranch
);
3030 bool mustReturnF
= exprNode_mustEscape (fbranch
);
3032 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred
),
3033 bool_unparse (mustReturnT
),
3034 bool_unparse (mustReturnF
)));
3036 if (exprNode_isDefined (fbranch
))
3038 loc
= exprNode_loc (fbranch
);
3042 loc
= exprNode_loc (tbranch
);
3045 llassert (usymtab_isDefined (ttab
));
3049 llassert (usymtab_isDefined (env
));
3050 llassert (ftab
->kind
== US_FBRANCH
);
3051 llassert (ttab
->kind
== US_TBRANCH
);
3054 ** For each element that is true guarded (i.e., if (x != NULL))
3055 ** make x = null in false branch,
3056 ** and x = notnull in true branch.
3057 ** unless x was set locally in that branch.
3058 ** For each element that is false guarded (x == NULL)
3059 ** make x = null in true, notnull in false.
3061 ** For each element that is either guarded (pred(x))
3065 sRefSet_allElements (tguards
, el
)
3067 updateNullState (el
, ttab
, ftab
, TRUE
);
3068 } end_sRefSet_allElements
;
3070 sRefSet_allElements (fguards
, el
)
3072 updateNullState (el
, ttab
, ftab
, FALSE
);
3073 } end_sRefSet_allElements
;
3077 ** if an entry is in both true and false, merge the entries,
3078 ** then replace original with new state.
3080 ** if an entry is in one table, merge it with the original.
3083 DPRINTF (("ftab: %d", ftab
->nentries
));
3085 for (i
= 0; i
< ftab
->nentries
; i
++)
3087 uentry fthis
= ftab
->entries
[i
];
3088 uentry old
= usymtab_lookupAux (env
, uentry_rawName (fthis
));
3089 usymId tindex
= usymtab_getIndex (ttab
, uentry_rawName (fthis
));
3091 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis
), uentry_unparseFull (old
)));
3093 if (uentry_isUndefined (old
))
3095 /* possible entry was added as an undefined id */
3096 DPRINTF (("Undefined! %s", uentry_rawName (fthis
)));
3100 if (usymtab_indexFound (tindex
))
3102 uentry tthis
= ttab
->entries
[tindex
];
3104 /* note that is this is in a nested branch,
3105 it may create a "new" old entry. */
3111 uentry_mergeState (fthis
, tthis
, loc
,
3112 mustReturnT
, FALSE
, FALSE
, cl
);
3116 uentry_mergeUses (fthis
, tthis
);
3119 uentry_setState (old
, fthis
);
3126 uentry_setState (old
, tthis
);
3127 uentry_mergeState (old
, fthis
, loc
, mustReturnF
,
3131 ttab
->entries
[tindex
] = uentry_undefined
;
3132 uentry_free (tthis
);
3136 uentry_mergeState (old
, fthis
, loc
, mustReturnF
, TRUE
, FALSE
, cl
);
3140 for (i
= 0; i
< ttab
->nentries
; i
++)
3142 uentry current
= ttab
->entries
[i
];
3144 DPRINTF (("ttab: %s", uentry_unparseFull (current
)));
3146 if (!uentry_isUndefined (current
))
3148 uentry old
= usymtab_lookupAux (env
, uentry_rawName (current
));
3150 DPRINTF (("Old: %s", uentry_unparseFull (old
)));
3152 if (uentry_isUndefined (old
))
3154 llcontbug (message ("Undefined entry: %s", uentry_rawName (current
)));
3160 uentry_mergeUses (current
, old
);
3161 uentry_setState (old
, current
);
3166 ** Assumes false branch is a fall-through if
3167 ** fbranch is not defined. This is true, unless
3168 ** where was some greivous error in processing
3169 ** the else branch of an if-then, in which case
3170 ** this is probably the right thing to do anyway.
3173 uentry_mergeState (old
, current
, loc
, mustReturnT
,
3177 DPRINTF (("==> %s", uentry_unparseFull (old
)));
3182 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3183 ** if they are present.
3186 llassert (NOALIAS (env
->aliases
, ttab
->aliases
));
3187 llassert (NOALIAS (env
->aliases
, ftab
->aliases
));
3189 aliasTable_free (env
->aliases
);
3191 env
->aliases
= aliasTable_levelUnionNew (ttab
->aliases
,
3192 ftab
->aliases
, env
->lexlevel
);
3194 aliasTable_fixSrefs (env
->aliases
);
3196 DPRINTF (("Aliases: %s", aliasTable_unparse (env
->aliases
)));
3198 /* exit true and false scopes */
3199 usymtab_quietPlainExitScope ();
3200 usymtab_quietPlainExitScope ();
3204 utab
->guards
= guardSet_levelUnionFree
3206 guardSet_invert (exprNode_getGuards (pred
)),
3212 utab
->guards
= guardSet_levelUnion (utab
->guards
,
3213 exprNode_getGuards (pred
),
3217 DPRINTF (("Here."));
3220 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3221 while (utab
->kind
== US_CBRANCH
)
3223 usymtab_quietPlainExitScope ();
3226 llassert (utab
->kind
!= US_CBRANCH
);
3230 usymtab_altBranch (/*@only@*/ guardSet guards
)
3234 usymtab parent
= utab
->env
;
3236 t
= usymtab_create (US_FBRANCH
, utab
, FALSE
);
3239 ** If we are in a case, need to close it. The C syntax
3240 ** is very liberal, so this kludge is necessary.
3243 usymtab_fixCases ();
3245 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3247 llassert (utab
->kind
== US_TBRANCH
);
3248 llassert (parent
!= GLOBAL_ENV
);
3250 guardSet_free (t
->guards
);
3253 aliasTable_free (t
->aliases
);
3254 t
->aliases
= aliasTable_copy (parent
->aliases
);
3260 usymtab_allDefined (void)
3261 /*@globals utab, globtab@*/
3265 llassert (utab
== globtab
);
3267 for (i
= 0; i
< utab
->nentries
; i
++)
3269 uentry e
= utab
->entries
[i
];
3271 if (uentry_isPriv (e
))
3273 ; /* no need to define it */
3277 if (context_getFlag (FLG_SPECUNDECL
))
3279 fileloc sloc
= uentry_whereSpecified (e
);
3280 fileloc dloc
= uentry_whereDeclared (e
);
3282 if (fileloc_isDefined (sloc
)
3283 && !uentry_isFakeTag (e
)
3284 && !fileloc_isDefined (dloc
))
3288 message ("%s %q specified but not declared",
3289 ekind_capName (uentry_getKind (e
)),
3290 uentry_getName (e
)),
3295 if (!uentry_isCodeDefined (e
))
3297 fileloc dloc
= uentry_whereDeclared (e
);
3299 if (fileloc_isLib (dloc
) || fileloc_isXHFile (dloc
))
3303 else if (fileloc_isDefined (dloc
))
3305 if (!uentry_isAnyTag (e
))
3307 if (fileloc_isUser (dloc
))
3311 message ("%s %q declared but not defined",
3312 ekind_capName (uentry_getKind (e
)),
3313 uentry_getName (e
)),
3315 DPRINTF (("decl: %s", uentry_unparseFull (e
)));
3321 fileloc sloc
= uentry_whereSpecified (e
);
3323 if (fileloc_isDefined (sloc
)
3324 && !fileloc_isImport (sloc
)
3325 && !fileloc_isLib (sloc
)
3326 && !fileloc_isPreproc (sloc
)
3327 && !uentry_isFakeTag (e
))
3329 if (uentry_isVariable (e
) || uentry_isFunction (e
))
3333 message ("%s %q specified but not declared or defined",
3334 ekind_capName (uentry_getKind (e
)),
3335 uentry_getName (e
)),
3342 message ("%s %q specified but not defined",
3343 ekind_capName (uentry_getKind (e
)),
3344 uentry_getName (e
)),
3354 void usymtab_exportHeader (void)
3359 for (i
= 0; i
< utab
->nentries
; i
++)
3361 uentry ce
= utab
->entries
[i
];
3363 if (!uentry_isDatatype (ce
)
3364 && !uentry_isAnyTag (ce
)
3365 && !uentry_isEitherConstant (ce
) && !uentry_isStatic (ce
)
3366 && !uentry_isExternal (ce
)
3367 && !uentry_isForward (ce
))
3369 fileloc fwhere
= uentry_whereDeclared (ce
);
3371 if (fileloc_isUndefined (fwhere
)
3372 && uentry_isFunction (ce
))
3374 fwhere
= uentry_whereDefined (ce
);
3377 if (fileloc_isDefined (fwhere
)
3378 && !fileloc_isHeader (fwhere
)
3379 && !fileloc_isXHFile (fwhere
)
3380 && !(fileloc_isSpecialFile (fwhere
)
3381 && !context_getFlag (FLG_UNUSEDSPECIAL
)))
3383 if (uentry_isVariable (ce
))
3386 (FLG_EXPORTHEADERVAR
,
3387 message ("%s %q exported but not declared in header file",
3388 ekind_capName (uentry_getKind (ce
)),
3389 uentry_getName (ce
)),
3392 uentry_showDefSpecInfo (ce
, fwhere
);
3397 if (!uentry_isIter (ce
)
3398 && !uentry_isEndIter (ce
)
3399 && !uentry_isExpandedMacro (ce
))
3401 if (uentry_isFunction (ce
)
3402 && cstring_equalLit (uentry_rawName (ce
), "main"))
3404 ; /* no error for main */
3410 message ("%s %q exported but not declared "
3412 ekind_capName (uentry_getKind (ce
)),
3413 uentry_getName (ce
)),
3416 uentry_showDefSpecInfo (ce
, fwhere
);
3426 void usymtab_exportLocal (void)
3431 for (i
= 0; i
< utab
->nentries
; i
++)
3433 uentry ce
= utab
->entries
[i
];
3435 if (!uentry_isDatatype (ce
) && !uentry_isAnyTag (ce
)
3436 && !uentry_isEitherConstant (ce
)
3437 && !uentry_isIter (ce
)
3438 && !uentry_isEndIter (ce
)
3439 && !uentry_isExpandedMacro (ce
)
3440 && uentry_isUsed (ce
))
3442 /* check static uses */
3443 filelocList fuses
= uentry_getUses (ce
);
3444 fileloc mod
= uentry_whereDefined (ce
);
3445 bool ok
= filelocList_isEmpty (fuses
);
3446 fileloc fwhere
= uentry_whereDeclared (ce
);
3448 if (fileloc_isSpecialFile (fwhere
)
3449 && !context_getFlag (FLG_UNUSEDSPECIAL
))
3451 ok
= TRUE
; /* no errors for special files */
3455 filelocList_elements (fuses
, uloc
)
3457 if (fileloc_isUndefined (uloc
) || !fileloc_sameModule (uloc
, mod
))
3460 /*@innerbreak@*/ break;
3462 } end_filelocList_elements
;
3469 message ("%s exported but not used outside %s: %q",
3470 ekind_capName (uentry_getKind (ce
)),
3471 fileloc_getBase (mod
),
3472 uentry_getName (ce
)),
3475 uentry_showDefSpecInfo (ce
, fwhere
);
3483 usymtab_allUsed (void)
3487 bool isFileStatic
= usymtab_inFileScope ();
3488 cstring last_file
= cstring_undefined
;
3490 for (i
= 0; i
< utab
->nentries
; i
++)
3492 bool hasError
= FALSE
;
3493 uentry ce
= utab
->entries
[i
];
3494 fileloc fwhere
= uentry_whereDeclared (ce
);
3496 if (fileloc_isUndefined (fwhere
))
3498 fwhere
= uentry_whereDefined (ce
);
3501 if (fileloc_isInvalid (fwhere
)
3502 || fileloc_isLib (fwhere
)
3503 || fileloc_isBuiltin (fwhere
)
3504 || ((fileloc_isSpecialFile (fwhere
)
3505 || fileloc_isSpecialFile (uentry_whereDefined (ce
)))
3506 && !context_getFlag (FLG_UNUSEDSPECIAL
)))
3510 else if (!uentry_wasUsed (ce
) && !uentry_isAnyTag (ce
))
3512 cstring fname
= fileloc_filename (fwhere
);
3514 if (cstring_isUndefined (last_file
))
3518 else if (cstring_equal (fname
, last_file
))
3527 if (uentry_isParam (ce
))
3529 if (context_inMacro ())
3531 sRef cref
= uentry_getSref (ce
);
3533 if (uentry_isYield (ce
))
3535 ; /* no checks (for now) */
3537 else if (sRef_isSafe (cref
))
3543 if (uentry_hasRealName (ce
))
3546 optgenerror (FLG_MACROPARAMS
,
3547 message ("Macro parameter %q not used",
3548 uentry_getName (ce
)),
3555 if (cstring_equalFree (uentry_getName (ce
),
3556 cstring_makeLiteral ("...")))
3562 hasError
= optgenerror (FLG_PARAMUNUSED
,
3563 message ("Parameter %q not used",
3564 uentry_getName (ce
)),
3569 else if (uentry_isFunction (ce
) || uentry_isIter (ce
))
3571 if (fileloc_isUser (fwhere
))
3573 hasError
= optgenerror
3575 message ("%q %q declared but not used",
3577 (uentry_isIter (ce
) ? "Iterator"
3578 : (isFileStatic
? "File static function" : "Function")),
3579 uentry_getName (ce
)),
3583 else if (uentry_isEndIter (ce
))
3585 ; /* no error (already reported for iter */
3587 else if (uentry_isEnumConstant (ce
))
3589 if (fileloc_isUser (fwhere
))
3591 hasError
= optgenerror
3593 message ("Enum member %q not used",
3594 uentry_getName (ce
)),
3598 else if (uentry_isConstant (ce
))
3600 if (fileloc_isUser (fwhere
))
3602 hasError
= optgenerror
3604 message ("Constant %q declared but not used",
3605 uentry_getName (ce
)),
3609 else if (uentry_isDatatype (ce
))
3611 if (fileloc_isUser (fwhere
))
3613 hasError
= optgenerror
3615 message ("Type %q declared but not used",
3616 uentry_getName (ce
)),
3620 else if (!uentry_isRefParam (ce
) && !uentry_isExpandedMacro (ce
))
3621 { /* errors for ref params will be reported in the next scope */
3622 llassertprint (uentry_isVar (ce
),
3623 ("ce: %s", uentry_unparseFull (ce
)));
3625 if (ctype_isFunction (uentry_getType (ce
)))
3627 if (fileloc_isUser (fwhere
))
3629 hasError
= optgenerror
3631 message ("%q %q declared but not used",
3633 (isFileStatic
? "File static function"
3635 uentry_getName (ce
)),
3641 if (fileloc_isUser (fwhere
))
3645 hasError
= optgenerror
3647 message ("%q %q declared but not used",
3649 (isFileStatic
? "File static variable"
3651 uentry_getName (ce
)),
3661 else if ((uentry_isDatatype (ce
) || uentry_isAnyTag (ce
)))
3662 { /* check all fields */
3663 ctype ct
= uentry_getRealType (ce
);
3666 while (ctype_isAP (ct
))
3668 ct
= ctype_getBaseType (ct
);
3671 if (ctype_isSU (ct
))
3673 uentryList fields
= ctype_getFields (ct
);
3675 uentryList_elements (fields
, field
)
3677 if (!uentry_isUsed (field
))
3679 if (uentry_hasName (ce
))
3681 hasError
|= optgenerror
3683 message ("Field %q of %s %q declared but not used",
3684 uentry_getName (field
),
3685 cstring_makeLiteralTemp
3686 (ctype_isStruct (ct
) ? "structure" : "union"),
3687 uentry_getName (ce
)),
3688 uentry_whereEarliest (field
));
3694 ** Can't report these errors for unnamed structs.
3695 ** No way to tell when there are multiple consistent
3696 ** unnamed structure types. (Could go through table
3697 ** and mark them all unused...)
3699 hasError |= optgenerror
3701 message ("Field %q of unnamed %s declared but not used",
3702 uentry_getName (field),
3703 cstring_makeLiteralTemp
3704 (ctype_isStruct (ct) ? "structure" : "union")),
3705 uentry_whereEarliest (field));
3710 uentry_setUsed (field
, fileloc_undefined
);
3712 } end_uentryList_elements
;
3722 if (uentry_isParam (ce
) && context_inMacro ())
3724 if (fileloc_isDefined (uentry_whereSpecified (ce
)))
3726 uentry_showWhereSpecified (ce
);
3731 uentry_showDefSpecInfo (ce
, fwhere
);
3734 uentry_setUsed (ce
, fileloc_undefined
);
3740 checkGlobalReturn (uentry glob
, sRef orig
)
3742 sRef sr
= uentry_getSref (glob
);
3744 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3745 uentry_unparseFull (glob
),
3746 sRef_unparseFull (orig
),
3747 sRef_unparseFull (sr
)));
3749 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig
))));
3751 if (context_getFlag (FLG_GLOBSTATE
))
3753 DPRINTF (("Is killed: %s", sRef_unparseFull (orig
)));
3755 if (sRef_isKilledGlob (orig
))
3757 if (sRef_isStateUndefined (sr
)
3758 || sRef_isUnuseable (sr
)
3759 || sRef_isStateUnknown (sr
)
3760 || sRef_isDead (sr
))
3766 ctype ct
= ctype_realType (uentry_getType (glob
));
3768 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob
)));
3770 if (ctype_isVisiblySharable (ct
))
3775 ("Killed global %q (type %s) not released before return",
3776 uentry_getName (glob
),
3777 ctype_unparse (ct
)),
3780 sRef_showStateInfo (sr
);
3785 sRef_protectDerivs ();
3786 (void) transferChecks_globalDestroyed (sr
, g_currentloc
);
3787 sRef_clearProtectDerivs ();
3793 if (sRef_isStateUndefined (sr
))
3795 if (optgenerror (FLG_GLOBSTATE
,
3797 ("Function returns with global %q undefined",
3798 uentry_getName (glob
)),
3801 sRef_showStateInfo (sr
);
3806 if (sRef_isDead (sr
) || sRef_isKept (sr
))
3810 message ("Function returns with global %q "
3811 "referencing %s storage",
3812 uentry_getName (glob
),
3813 cstring_makeLiteralTemp (sRef_isDead (sr
) ? "released" : "kept")),
3816 if (sRef_isKept (sr
))
3818 sRef_showAliasInfo (sr
);
3822 sRef_showStateInfo (sr
);
3825 sRef_setDefState (sr
, SS_UNKNOWN
, fileloc_undefined
);
3829 DPRINTF (("Here: %s / %s",
3830 uentry_unparseFull (glob
),
3831 sRef_unparseFull (sr
)));
3833 if (ctype_isRealPointer (uentry_getType (glob
))
3834 && sRef_possiblyNull (sr
)
3835 && !uentry_possiblyNull (glob
))
3839 message ("Function returns with non-null global %q "
3840 "referencing null storage",
3841 uentry_getName (glob
)),
3844 sRef_showNullInfo (sr
);
3849 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob
)));
3850 transferChecks_globalReturn (glob
);
3858 ** remember: check alias globals
3861 void usymtab_checkFinalScope (bool isReturn
)
3864 bool mustDefine
= context_getFlag (FLG_MUSTDEFINE
);
3865 sRefSet checked
= sRefSet_new ();
3866 usymtab stab
= utab
;
3870 ** need to check all scopes out to function parameters.
3875 for (i
= 0; i
< stab
->nentries
; i
++)
3877 uentry ce
= stab
->entries
[i
];
3878 sRef sr
= uentry_getSref (ce
);
3879 sRef rb
= sRef_getRootBase (sr
);
3883 ** Shouldn't check if shadow checked in deeper scope:
3888 uentry oue
= usymtab_lookupQuietNoAlt (utab
, uentry_observeRealName (ce
));
3890 if (!uentry_sameObject (ce
, oue
))
3892 /* what if it is one an alternate branch? */
3893 /*@innercontinue@*/ continue;
3897 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce
)));
3899 if (ctype_isFunction (uentry_getType (ce
)))
3901 /*@innercontinue@*/ continue;
3904 if (uentry_isAnyParam (ce
)
3905 || uentry_isRefParam (ce
)
3906 || sRef_isFileOrGlobalScope (rb
))
3908 /* Don't do the loseref check...but should check state! */
3909 DPRINTF (("Skipping check 1"));
3911 else if (sRef_isDefinitelyNull (sr
)
3912 || usymtab_isDefinitelyNull (sr
))
3915 ** No state reference errors for definitely null references.
3918 DPRINTF (("Skipping check 2"));
3922 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce
),
3923 sRef_unparseFull (sr
)));
3925 tvalues
= sRef_getValueTable (sr
);
3927 valueTable_elements (tvalues
, fkey
, fval
) {
3928 metaStateInfo minfo
;
3929 cstring msg
= cstring_undefined
;
3931 minfo
= context_lookupMetaStateInfo (fkey
);
3932 llassert (metaStateInfo_isDefined (minfo
));
3934 if (stateValue_isError (fval
)
3935 || sRef_isStateUndefined (sr
)) /* No errors for undefined state */
3937 DPRINTF (("Skipping check 3"));
3941 DPRINTF (("Check: %s / %s / %s", fkey
,
3942 metaStateInfo_unparse (minfo
),
3943 stateValue_unparse (fval
)));
3945 minfo
= context_lookupMetaStateInfo (fkey
);
3948 stateCombinationTable sctable
;
3950 sctable
= metaStateInfo_getTransferTable (minfo
);
3951 (void) stateCombinationTable_lookup (sctable
,
3952 stateValue_getValue (fval
), sctable
->size
, &msg
);
3955 if (cstring_isDefined (msg
))
3960 ("%s loses reference %q in invalid state %q (%s)",
3961 cstring_makeLiteralTemp (isReturn
? "Return" : "Scope exit"),
3962 uentry_getName (ce
),
3963 stateValue_unparseValue (fval
, minfo
),
3967 stateValue_show (fval
, minfo
);
3971 DPRINTF (("Suppressed transfer error: %s", msg
));
3975 } end_valueTable_elements
;
3978 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce
)));
3980 if (!sRefSet_member (checked
, sr
) && !sRef_isFileOrGlobalScope (rb
))
3982 if (ctype_isRealSU (uentry_getType (ce
))
3983 && !uentry_isAnyParam (ce
)
3984 && !uentry_isRefParam (ce
)
3985 && !uentry_isStatic (ce
)
3986 && !sRef_isDependent (sr
)
3987 && !sRef_isOwned (sr
))
3989 sRefSet als
= usymtab_allAliases (sr
);
3991 if (sRefSet_isEmpty (als
))
3993 transferChecks_localDestroyed (sr
, g_currentloc
);
3997 /* aliased, no problem */ ;
4003 (!uentry_isStatic (ce
)
4004 && ((sRef_isNewRef (sr
))
4005 || (((sRef_isOnly (sr
) || sRef_isFresh (sr
)
4006 || sRef_isKeep (sr
) || sRef_isOwned (sr
))
4007 && !sRef_isDead (sr
))
4008 && (!sRef_definitelyNull (sr
))
4009 && (!usymtab_isDefinitelyNull (sr
)))))
4011 bool hasError
= TRUE
;
4013 DPRINTF (("Checking: %s", sRef_unparseFull (sr
)));
4016 ** If its a scope exit, check if there is an alias.
4017 ** If so, make it only. If not, there is an error.
4022 if (transferChecks_canLoseReference (sr
, g_currentloc
))
4024 DPRINTF (("Can lose!"));
4031 if (sRef_hasLastReference (sr
))
4033 sRef ar
= sRef_getAliasInfoRef (sr
);
4036 (sRef_isFresh (ar
) ? FLG_MUSTFREEFRESH
: FLG_MUSTFREEONLY
,
4038 ("Last reference %q to %s storage %qnot %q before %q",
4040 alkind_unparse (sRef_getAliasKind (sr
)),
4041 sRef_unparseOpt (ar
),
4042 cstring_makeLiteral (sRef_isKeep (sr
)
4043 ? "transferred" : "released"),
4044 cstring_makeLiteral (isReturn
4045 ? "return" : "scope exit")),
4048 sRef_showRefLost (sr
);
4051 else if (sRef_isNewRef (sr
))
4054 (sRef_isFresh (sr
) ? FLG_MUSTFREEFRESH
: FLG_MUSTFREEONLY
,
4056 ("%q %q not released before %q",
4058 (alkind_isKillRef (sRef_getOrigAliasKind (sr
))
4059 ? "Kill reference parameter" : "New reference"),
4060 uentry_getName (ce
),
4061 cstring_makeLiteral (isReturn
4062 ? "return" : "scope exit")),
4065 sRef_showAliasInfo (sr
);
4070 if (ctype_isRealSU (sRef_getType (sr
)))
4072 transferChecks_structDestroyed (sr
, g_currentloc
);
4077 (sRef_isFresh (sr
) ? FLG_MUSTFREEFRESH
: FLG_MUSTFREEONLY
,
4079 ("%s storage %q not %q before %q",
4080 alkind_capName (sRef_getAliasKind (sr
)),
4081 uentry_getName (ce
),
4082 cstring_makeLiteral (sRef_isKeep (sr
)
4083 ? "transferred" : "released"),
4084 cstring_makeLiteral (isReturn
4085 ? "return" : "scope exit")),
4088 sRef_showAliasInfo (sr
);
4089 DPRINTF (("Storage: %s", sRef_unparseFull (sr
)));
4101 if (mustDefine
&& uentry_isOut (ce
))
4103 /* No error if its dead (either only or error already reported */
4104 if (!sRef_isReallyDefined (sr
) && !sRef_isDead (sr
))
4108 message ("Out storage %q not defined before %q",
4109 uentry_getName (ce
),
4111 (isReturn
? "return" : "scope exit")),
4114 DPRINTF (("sr: %s", sRef_unparseFull (sr
)));
4119 ** also check state is okay
4122 if (usymtab_lexicalLevel () > functionScope
4123 && uentry_isVariable (ce
)
4124 && (sRef_isLocalVar (sr
)
4125 && (sRef_isDependent (sr
) || sRef_isLocalState (sr
))))
4127 sRefSet ab
= usymtab_aliasedBy (sr
);
4129 /* should do something more efficient here */
4131 if (sRefSet_isEmpty (ab
))
4133 /* and no local ref */
4134 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce
)));
4135 transferChecks_loseReference (ce
);
4149 checked
= sRefSet_insert (checked
, sr
);
4152 llassert (usymtab_isDefined (stab
->env
));
4154 if (usymtab_isBranch (stab
))
4156 stab
= usymtab_dropEnv (stab
);
4163 llassert (stab
!= usymtab_undefined
);
4164 } while (isReturn
&& (stab
->lexlevel
>= paramsScope
));
4166 sRefSet_free (checked
);
4170 ** all globals are appropriately defined
4171 ** all parameters are appropriately defined
4172 ** special clauses are followed
4175 if (isReturn
|| (utab
->lexlevel
== paramsScope
))
4177 uentry fcn
= context_getHeader ();
4178 uentryList params
= context_getParams ();
4179 globSet uglobs
= context_getUsedGlobs ();
4180 globSet sglobs
= context_getGlobs ();
4182 if (isReturn
&& context_maybeSet (FLG_GLOBALIAS
))
4184 aliasTable_checkGlobs (utab
->aliases
);
4188 ** state clauses (ensures, defines, sets, allocates, releases)
4191 if (uentry_hasStateClauseList (fcn
))
4193 stateClauseList clauses
= uentry_getStateClauseList (fcn
);
4195 stateClauseList_elements (clauses
, cl
)
4197 if (stateClause_isAfter (cl
) && !stateClause_isGlobal (cl
))
4199 if (stateClause_setsMetaState (cl
))
4201 sRefSet rfs
= stateClause_getRefs (cl
);
4202 qual q
= stateClause_getMetaQual (cl
);
4203 annotationInfo ainfo
= qual_getAnnotationInfo (q
);
4204 metaStateInfo minfo
= annotationInfo_getState (ainfo
);
4205 cstring key
= metaStateInfo_getName (minfo
);
4206 int mvalue
= annotationInfo_getValue (ainfo
);
4208 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl
)));
4210 sRefSet_elements (rfs
, el
)
4212 sRef base
= sRef_getRootBase (el
);
4214 if (sRef_isResult (base
))
4217 ** This is checked for return transfers.
4221 else if (sRef_isParam (base
) || sRef_isGlobalMarker (base
))
4223 sRef sr
= sRef_updateSref (base
);
4224 sr
= sRef_fixBase (el
, sr
);
4226 if (!sRef_checkMetaStateValue (sr
, key
, mvalue
))
4231 ("Ensures clause not satisfied%q (state is %q): %q",
4232 sRef_isGlobalMarker (sr
)
4234 : message (" by %q", sRef_unparse (sr
)),
4235 stateValue_unparseValue (sRef_getMetaStateValue (sr
, key
),
4237 stateClause_unparse (cl
)),
4240 sRef_showMetaStateInfo (sr
, key
);
4246 if (sRef_isMeaningful (el
))
4251 } end_sRefSet_elements
;
4255 /* evs - 2000 07 10 - added this */
4256 sRefTest tst
= stateClause_getPostTestFunction (cl
);
4257 sRefSet rfs
= stateClause_getRefs (cl
);
4259 sRefSet_elements (rfs
, el
)
4261 sRef base
= sRef_getRootBase (el
);
4263 if (sRef_isResult (base
))
4266 ** This is checked for return transfers.
4271 else if (sRef_isParam (base
))
4273 sRef sr
= sRef_updateSref (base
);
4274 sr
= sRef_fixBase (el
, sr
);
4276 if (tst
!= NULL
&& !tst (sr
))
4279 (stateClause_postErrorCode (cl
),
4280 message ("%s storage %qcorresponds to "
4281 "storage listed in %q clause",
4282 stateClause_postErrorString (cl
, sr
),
4283 sRef_unparseOpt (sr
),
4284 stateClause_unparseKind (cl
)),
4287 sRefShower ss
= stateClause_getPostTestShower (cl
);
4294 DPRINTF (("Storage: %s", sRef_unparseFull (sr
)));
4300 if (sRef_isMeaningful (el
))
4305 } end_sRefSet_elements
;
4308 } end_stateClauseList_elements
;
4312 ** check parameters on return
4315 uentryList_elements (params
, arg
)
4317 if (!uentry_isElipsisMarker (arg
))
4319 ctype rt
= ctype_realType (uentry_getType (arg
));
4321 if (ctype_isMutable (rt
) || ctype_isSU (rt
))
4323 uentry param
= usymtab_lookupQuiet (utab
, uentry_rawName (arg
));
4324 DPRINTF (("Check param return: %s", uentry_unparseFull (param
)));
4325 transferChecks_paramReturn (param
);
4328 } end_uentryList_elements
;
4330 DPRINTF (("Check global return: %s",
4331 globSet_unparse (sglobs
)));
4333 globSet_allElements (sglobs
, el
)
4335 sRef orig
= el
; /*! sRef_updateSref (el); */ /*!!!*/
4336 uentry current
= sRef_getUentry (el
);
4338 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el
),
4339 uentry_unparseFull (current
)));
4341 if (uentry_isVariable (current
) && !uentry_isRealFunction (current
))
4343 checkGlobalReturn (current
, orig
);
4345 } end_globSet_allElements
;
4347 globSet_allElements (uglobs
, el
)
4349 if (!globSet_member (sglobs
, el
))
4351 uentry current
= sRef_getUentry (el
);
4353 if (uentry_isVariable (current
)
4354 && !uentry_isRealFunction (current
))
4356 checkGlobalReturn (current
, sRef_undefined
);
4359 } end_globSet_allElements
;
4364 usymtab_quietExitScope (fileloc loc
)
4365 /*@globals utab, globtab, filetab; @*/
4368 usymtab t
= utab
->env
;
4370 DPRINTF (("Quiet exit scope [%p]", utab
));
4372 if (utab
->reftable
!= NULL
)
4376 for (i
= 0; i
< utab
->nentries
; i
++)
4378 uentry current
= utab
->entries
[i
];
4379 uentry old
= usymtab_lookupAux (t
, uentry_rawName (current
));
4381 uentry_mergeState (old
, current
, loc
, FALSE
, FALSE
, FALSE
, NOCLAUSE
);
4385 llassert (t
!= NULL
);
4387 if (t
->lexlevel
> paramsScope
)
4389 t
->guards
= guardSet_levelUnion (t
->guards
, utab
->guards
, t
->lexlevel
);
4390 t
->aliases
= aliasTable_levelUnionSeq (t
->aliases
, utab
->aliases
,
4392 utab
->aliases
= aliasTable_undefined
;
4395 t
->mustBreak
= utab
->mustBreak
;
4396 t
->exitCode
= utab
->exitCode
;
4398 DPRINTF (("Free level [%p]", utab
));
4399 usymtab_freeLevel (utab
);
4404 usymtab_checkAllValid ();
4409 ** Exit a scope with no checking, lose alias states.
4410 ** (When should this be used?)
4413 void usymtab_quietPlainExitScope (void)
4414 /*@globals utab, globtab, filetab@*/
4417 usymtab t
= utab
->env
;
4419 llassert (t
!= NULL
);
4420 llassert (NOALIAS (utab
->aliases
, t
->aliases
));
4421 usymtab_freeLevel (utab
);
4425 void usymtab_exitScope (exprNode expr
)
4426 /*@globals utab, filetab, globtab@*/
4427 /*@modifies utab, globtab@*/
4429 usymtab ctab
= usymtab_undefined
;
4430 usymtab lctab
= usymtab_undefined
;
4431 bool mustReturn
= exprNode_mustEscape (expr
);
4433 DPRINTF (("Exit scope [%p]", utab
));
4435 if (utab
->kind
== US_CBRANCH
)
4438 ** save the case branches, remove the first non-cbranch
4443 while (utab
->kind
== US_CBRANCH
)
4447 llassert (utab
!= GLOBAL_ENV
);
4451 if (usymtab_isBranch (utab
))
4453 if (context_inMacro ())
4455 /* evs 2000-07-25 */
4456 /* Unparseable macro may end inside nested scope. Deal with it. */
4458 llerror (FLG_SYNTAX
,
4459 message ("Problem parsing macro body of %s (unbalanced scopes). "
4460 "Attempting to recover, recommend /*@notfunction@*/ before "
4461 "macro definition.",
4462 context_inFunctionName ()));
4464 while (usymtab_isBranch (utab
))
4467 llassert (utab
!= GLOBAL_ENV
);
4471 llcontbug (message ("%s: in branch: %q",
4472 cstring_fromChars (__func__
), usymtab_unparseStack ()));
4474 } /*@=branchstate@*/
4478 ** check all variables in scope were used
4482 ** bogus errors if this is the normal inside a switch,
4483 ** since cases have not been merged yet. Should probably
4484 ** still check this, but I'm too lazy at the moment...
4487 llassertfatal (utab
->env
!= GLOBAL_ENV
);
4489 if (utab
->env
->kind
!= US_SWITCH
)
4495 ** check aliasing: all only params are released (dead)
4496 ** definition: all out params are defined, all modified params
4497 ** are completely defined
4499 ** NOTE: note for exiting paramsScope, since checkReturn should be
4503 if (!mustReturn
&& (usymtab_lexicalLevel () > functionScope
))
4506 ** should only call this is end of scope is reachable...
4509 usymtab_checkFinalScope (FALSE
);
4512 if (usymtab_lexicalLevel () == paramsScope
&& context_inFunctionLike ())
4515 ** leaving a function, need to fix up globals
4518 uentryList params
= context_getParams ();
4519 globSet globs
= context_getUsedGlobs ();
4521 uentryList_elements (params
, ue
)
4523 uentry_fixupSref (ue
);
4524 } end_uentryList_elements
;
4526 clearFunctionTypes ();
4528 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs
)));
4530 globSet_allElements (globs
, el
)
4532 DPRINTF (("Fix: %s", sRef_unparseDebug (el
)));
4534 if (sRef_isCvar (el
))
4537 usymId index
= sRef_getScopeIndex (el
);
4539 if (sRef_isFileStatic (el
))
4541 llassert (usymtab_isDefined (filetab
));
4542 current
= usymtab_fetchIndex (filetab
, index
);
4546 current
= usymtab_fetchIndex (globtab
, index
);
4549 if (uentry_isVariable (current
))
4551 DPRINTF (("Fixup: %s", uentry_unparse (current
)));
4552 uentry_fixupSref (current
);
4556 DPRINTF (("Clear: %s", uentry_getSref (current
)));
4557 sRef_clearDerived (uentry_getSref (current
));
4561 sRef_clearDerived (el
); /* evans 2002-03-14 - this is the likely source of many crashes! */
4562 } end_globSet_allElements
;
4565 usymtab_quietExitScope (exprNode_loc (expr
));
4567 if (lctab
!= usymtab_undefined
)
4569 /*@i@*/ lctab
->env
= utab
;
4570 /*@i@*/ utab
= ctab
;
4571 /*@-branchstate@*/ } /*@=branchstate@*/
4576 usymtab_checkAllValid ();
4582 ** yikes! don't let the '170 kids see this one...
4586 usymtab_directParamNo (uentry ue
)
4588 if (uentry_isVar (ue
))
4590 sRef sr
= uentry_getSref (ue
);
4592 if (sRef_lexLevel (sr
) == functionScope
)
4594 usymId index
= sRef_getScopeIndex (sr
);
4596 if (index
< usymId_fromInt (uentryList_size (context_getParams ())))
4602 return usymId_invalid
;
4605 /*@dependent@*/ /*@exposed@*/ uentry
4606 usymtab_getParam (int paramno
)
4610 ** requires in a function context (checked)
4612 ** depends on no nested functions --- the function
4613 ** parameters are ALWAYS one scope inside the global scope
4614 ** and entered in order!
4618 if (!context_inFunctionLike ())
4619 llfatalbug (message ("%s: not in function context: %q",
4620 cstring_fromChars (__func__
), context_unparse ()));
4622 while (s
->lexlevel
> paramsScope
)
4627 llassert (usymtab_isDefined (s
));
4629 if (paramno
>= s
->nentries
)
4632 ** Parse errors lead to this.
4635 uentry err
= uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4638 uentry_markOwned (err
);
4642 return (s
->entries
[paramno
]);
4645 static /*@dependent@*/ /*@exposed@*/ uentry
4646 usymtab_getRefTab (/*@notnull@*/ usymtab u
, int level
, usymId index
)
4650 ue
= usymtab_getRefNoisy (u
, level
, index
);
4652 if (uentry_isUndefined (ue
))
4654 llbug (message ("%s: out of range: %d. level = %d",
4655 cstring_fromChars (__func__
), index
, level
));
4661 static /*@dependent@*/ /*@exposed@*/ usymtab
4662 usymtab_dropEnv (/*@notnull@*/ usymtab s
)
4664 if (s
->kind
== US_CBRANCH
)
4666 /* drop all cases (except in nested scopes) */
4670 llassert (s
!= GLOBAL_ENV
);
4671 } while (s
->kind
== US_CBRANCH
);
4673 else if (s
->kind
== US_FBRANCH
)
4675 /* skip the true branch */
4677 llassert (s
!= GLOBAL_ENV
);
4678 llassert (s
->kind
== US_TBRANCH
);
4684 llassert (s
!= GLOBAL_ENV
);
4691 /*@dependent@*/ /*@exposed@*/ uentry
4692 usymtab_getRefQuiet (int level
, usymId index
)
4698 llassert (s
!= NULL
);
4699 llassert (index
>= 0);
4701 if (level
> s
->lexlevel
)
4703 return uentry_undefined
;
4706 llassertprint (level
<= s
->lexlevel
, ("level: %d / lexlevel: %d",
4707 level
, s
->lexlevel
));
4709 while (s
->lexlevel
> level
)
4711 if (usymtab_isBranch (s
))
4713 int eindex
= refTable_lookup (s
, level
, index
);
4715 if (eindex
!= NOT_FOUND
)
4717 return (s
->entries
[eindex
]);
4721 s
= usymtab_dropEnv (s
);
4724 while (usymtab_isBranch (s
) && s
->lexlevel
== level
)
4726 int eindex
= refTable_lookup (s
, level
, index
);
4728 if (eindex
!= NOT_FOUND
)
4730 return (s
->entries
[eindex
]);
4733 s
= usymtab_dropEnv (s
);
4736 if (index
>= usymId_fromInt (s
->nentries
))
4738 return uentry_undefined
;
4741 llassert (!uentry_isUndefined (s
->entries
[index
]));
4743 return s
->entries
[index
];
4746 static /*@dependent@*/ /*@exposed@*/ uentry
4747 usymtab_getRefNoisy (/*@notnull@*/ usymtab s
, int level
, usymId index
)
4750 uentry ue
= uentry_undefined
;
4752 llassert (index
>= 0);
4754 while (s
->lexlevel
> level
)
4756 if (usymtab_isBranch (s
))
4758 int eindex
= refTable_lookup (s
, level
, index
);
4760 if (eindex
!= NOT_FOUND
)
4762 ue
= s
->entries
[eindex
];
4766 while (!usymtab_isBranch (otab
))
4768 otab
= usymtab_dropEnv (otab
);
4769 llassert (otab
!= GLOBAL_ENV
);
4772 if (refTable_lookup (otab
, level
, index
) == NOT_FOUND
)
4774 ue
= usymtab_addRefEntry (otab
, uentry_rawName (ue
));
4786 s
= usymtab_dropEnv (s
);
4789 llassert (usymtab_isDefined (s
));
4791 while (usymtab_isBranch (s
) && s
->lexlevel
== level
)
4793 int eindex
= refTable_lookup (s
, level
, index
);
4795 if (eindex
!= NOT_FOUND
)
4797 ue
= s
->entries
[eindex
];
4801 while (!usymtab_isBranch (otab
))
4803 otab
= usymtab_dropEnv (otab
);
4804 llassert (otab
!= GLOBAL_ENV
);
4807 ue
= usymtab_addRefEntry (otab
, uentry_rawName (ue
));
4817 s
= usymtab_dropEnv (s
);
4820 if (s
->lexlevel
== level
&& (index
< usymId_fromInt (s
->nentries
)))
4822 ue
= s
->entries
[index
];
4824 if (uentry_isValid (ue
))
4828 while (!usymtab_isBranch (otab
))
4830 otab
= usymtab_dropEnv (otab
);
4832 if (otab
== GLOBAL_ENV
)
4838 ue
= usymtab_addRefEntry (otab
, uentry_rawName (ue
));
4849 if (index
>= usymId_fromInt (s
->nentries
))
4851 return uentry_undefined
;
4854 llassert (!uentry_isUndefined (s
->entries
[index
]));
4856 return s
->entries
[index
];
4860 ** looking up entries
4862 ** If entry is inside a branch, then copy it, and put it into
4863 ** the branch table.
4867 int refTable_lookup (/*@notnull@*/ usymtab ut
, int level
, usymId index
)
4869 refTable rt
= ut
->reftable
;
4872 llassertfatal (rt
!= NULL
);
4874 for (i
= 0; i
< ut
->nentries
; i
++)
4876 llassertfatal (rt
[i
] != NULL
);
4877 if (rt
[i
]->level
== level
&& rt
[i
]->index
== usymId_toInt (index
))
4887 /*@only@*/ refentry
refentry_create (int level
, int index
)
4889 refentry r
= (refentry
) dmalloc (sizeof (*r
));
4897 static /*@dependent@*/ /*@exposed@*/ uentry
4898 usymtab_addRefEntry (/*@notnull@*/ usymtab s
, cstring k
)
4902 if (ut
->reftable
== NULL
)
4904 DPRINTF (("Adding ref entry without reftable: %s", k
));
4905 return uentry_undefined
;
4908 llassert (ut
->reftable
!= NULL
);
4910 while (s
!= GLOBAL_ENV
)
4912 usymId eindex
= usymtab_getIndex (s
, k
);
4914 if (usymtab_indexFound (eindex
))
4916 uentry current
= s
->entries
[eindex
];
4918 if (uentry_isVar (current
) && !ctype_isFunction (uentry_getType (current
)))
4922 DPRINTF (("Here: copying %s", uentry_unparse (current
)));
4923 if (uentry_isNonLocal (current
))
4925 ue
= uentry_copy (current
);
4929 ue
= uentry_copyNoSave (current
);
4932 DPRINTF (("Here: copying %s", uentry_unparse (ue
)));
4933 usymtab_addEntryQuiet (ut
, ue
);
4934 DPRINTF (("Okay..."));
4936 if (s
->reftable
!= NULL
)
4938 refentry ref
= s
->reftable
[eindex
];
4940 ut
->reftable
[ut
->nentries
- 1]
4941 = refentry_create (ref
->level
, ref
->index
);
4945 ut
->reftable
[ut
->nentries
- 1]
4946 = refentry_create (s
->lexlevel
, usymId_toInt (eindex
));
4957 s
= usymtab_dropEnv (s
);
4960 return uentry_undefined
;
4963 static uentry
usymtab_lookupAux (usymtab s
, cstring k
)
4965 DPRINTF (("Lookup: %s", k
));
4967 while (s
!= GLOBAL_ENV
)
4969 usymId eindex
= usymtab_getIndex (s
, k
);
4971 if (usymtab_indexFound (eindex
))
4973 uentry ret
= s
->entries
[eindex
];
4974 DPRINTF (("Found: %s", uentry_unparseFull (ret
)));
4978 if (s
->kind
== US_TBRANCH
||
4979 s
->kind
== US_FBRANCH
||
4980 s
->kind
== US_CBRANCH
) /* all branches except US_SWITCH */
4982 uentry ret
= usymtab_addRefEntry (s
, k
);
4983 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret
)));
4990 return uentry_undefined
;
4993 static /*@dependent@*/ /*@exposed@*/ uentry
4994 usymtab_lookupQuietAux (usymtab s
, cstring k
, bool noalt
)
4996 while (s
!= GLOBAL_ENV
)
4998 usymId eindex
= usymtab_getIndex (s
, k
);
5000 if (usymtab_indexFound (eindex
))
5002 uentry ret
= s
->entries
[eindex
];
5006 if (noalt
&& usymtab_isBranch (s
))
5008 s
= usymtab_dropEnv (s
);
5012 llassert (s
!= NULL
);
5017 return uentry_undefined
;
5020 static /*@exposed@*/ /*@dependent@*/ uentry
5021 usymtab_lookupQuiet (usymtab s
, cstring k
)
5023 return usymtab_lookupQuietAux (s
, k
, FALSE
);
5026 static /*@exposed@*/ /*@dependent@*/ uentry
5027 usymtab_lookupQuietNoAlt (usymtab s
, cstring k
)
5029 return usymtab_lookupQuietAux (s
, k
, TRUE
);
5032 /*@dependent@*/ /*@observer@*/ uentry
5033 usymtab_lookupSafe (cstring k
)
5036 DPRINTF (("Lookup safe: %s", k
));
5037 return (usymtab_lookupAux (utab
, k
));
5040 /*@dependent@*/ /*@observer@*/ uentry
5041 usymtab_lookupSafeScope (cstring k
, int lexlevel
)
5045 ** This is necessary to deal with shadowed variables that are referenced
5046 ** through aliases inside the shadowed scope. It would be better if
5047 ** lookup could take an sRef as a parameter.
5052 while (tab
!= GLOBAL_ENV
&& tab
->lexlevel
> lexlevel
) {
5053 uentry ret
= usymtab_lookupAux (tab
, k
);
5055 if (uentry_isValid (ret
)) {
5056 sRef sr
= uentry_getSref (ret
);
5058 if (sRef_isCvar (sr
) && sRef_lexLevel (sr
) > lexlevel
) {
5059 tab
= usymtab_dropEnv (tab
);
5066 return uentry_undefined
;
5070 usymtab_lookupExpose (cstring k
)
5073 uentry ce
= usymtab_lookupAux (utab
, k
);
5075 if (uentry_isUndefined (ce
))
5077 llfatalbug (message ("%s: not found: *%s*", cstring_fromChars (__func__
), k
));
5080 if (uentry_isPriv (ce
))
5082 llfatalbug (message ("%s: private: *%s*", cstring_fromChars (__func__
), k
));
5088 uentry
usymtab_lookupExposeGlob (cstring k
)
5090 return (usymtab_lookupGlobSafe (k
));
5093 uentry
usymtab_lookupGlob (cstring k
)
5094 /*@globals globtab@*/
5096 uentry ce
= usymtab_lookupAux (globtab
, k
);
5098 if (uentry_isUndefined (ce
))
5099 llfatalbug (message ("%s: not found: %s", cstring_fromChars (__func__
), k
));
5101 if (uentry_isPriv (ce
))
5102 llfatalbug (message ("%s: private: %s", cstring_fromChars (__func__
), k
));
5104 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce
)));
5108 /*@observer@*/ uentry
5109 usymtab_lookupGlobSafe (cstring k
)
5110 /*@globals globtab@*/
5112 uentry ce
= usymtab_lookupAux (globtab
, k
);
5113 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce
)));
5117 uentry
usymtab_lookupEither (cstring k
)
5120 uentry ce
= usymtab_lookupSafe (k
);
5122 if (uentry_isUndefined (ce
))
5123 llfatalerror (message ("%s: not found: %s", cstring_fromChars (__func__
), k
));
5125 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce
)));
5130 usymtab_lookupType (cstring k
)
5131 /*@globals globtab@*/
5133 typeId uid
= usymtab_getTypeId (k
);
5135 if (typeId_isInvalid (uid
))
5137 llcontbug (message ("%s: not found: %s", cstring_fromChars (__func__
), k
));
5138 return ctype_unknown
;
5141 return (uentry_getRealType (usymtab_getTypeEntry (uid
)));
5145 usymtab_lookupAbstractType (cstring k
) /*@globals globtab@*/
5147 typeId uid
= usymtab_getTypeId (k
);
5149 if (typeId_isInvalid (uid
))
5151 llcontbug (message ("%s: not found: %s", cstring_fromChars (__func__
), k
));
5152 return ctype_unknown
;
5155 return (uentry_getAbstractType (usymtab_getTypeEntry (uid
)));
5159 ** if there is an unnamed lcl-specified struct tag matching
5160 ** the uentryList, return its datatype. Otherwise, returns
5165 usymtab_structFieldsType (uentryList f
)
5166 /*@globals globtab@*/
5168 return (usymtab_suFieldsType (f
, TRUE
));
5172 usymtab_unionFieldsType (uentryList f
)
5173 /*@globals globtab@*/
5175 return (usymtab_suFieldsType (f
, FALSE
));
5179 usymtab_suFieldsType (uentryList f
, bool isStruct
)
5180 /*@globals globtab@*/
5184 DPRINTF (("Fields: %s", uentryList_unparse (f
)));
5186 if (fileloc_isSpec (g_currentloc
))
5188 return (ctype_undefined
);
5191 for (i
= 0; i
< globtab
->nentries
; i
++)
5193 uentry current
= globtab
->entries
[i
];
5196 ? uentry_isStructTag (current
) : uentry_isUnionTag (current
)))
5198 if (isFakeTag (uentry_rawName (current
)))
5200 ctype ct
= uentry_getType (current
);
5202 DPRINTF (("Check: %s", ctype_unparse (ct
)));
5204 if ((isStruct
? ctype_isStruct (ct
) : ctype_isUnion (ct
))
5206 (uentry_isSpecified (current
)
5207 && uentryList_equivFields (f
, ctype_getFields (ct
))))
5209 return uentry_getAbstractType (current
);
5219 return ctype_undefined
;
5223 usymtab_enumEnumNameListType (enumNameList f
)
5224 /*@globals globtab@*/
5228 for (i
= 0; i
< globtab
->nentries
; i
++)
5230 uentry current
= globtab
->entries
[i
];
5232 if (uentry_isEnumTag (current
))
5234 if (isFakeTag (uentry_rawName (current
)))
5236 ctype ct
= uentry_getType (current
);
5238 if (ctype_isEnum (ct
) && (enumNameList_match (f
, ctype_elist (ct
))))
5240 return uentry_getType (current
);
5246 return ctype_undefined
;
5250 usymtab_exists (cstring k
)
5253 uentry ce
= usymtab_lookupSafe (k
);
5254 return (!(uentry_isUndefined (ce
)) && !(uentry_isPriv (ce
)));
5258 usymtab_existsReal (cstring k
)
5261 uentry ce
= usymtab_lookupSafe (k
);
5263 return (!(uentry_isUndefined (ce
))
5264 && !(uentry_isPriv (ce
))
5265 && !(uentry_isExpandedMacro (ce
)));
5269 usymtab_existsGlob (cstring k
)
5270 /*@globals globtab@*/
5272 uentry ce
= usymtab_lookupAux (globtab
, k
);
5274 return (!(uentry_isUndefined (ce
)) && !(uentry_isPriv (ce
)));
5278 usymtab_existsEither (cstring k
)
5281 uentry ce
= usymtab_lookupAux (utab
, k
);
5283 return (uentry_isValid (ce
));
5287 usymtab_existsGlobEither (cstring k
)
5288 /*@globals globtab@*/
5290 uentry ce
= usymtab_lookupAux (globtab
, k
);
5292 return (uentry_isValid (ce
));
5296 usymtab_existsType (cstring k
)
5297 /*@globals globtab@*/
5299 uentry ce
= usymtab_lookupAux (globtab
, k
);
5301 return (!(uentry_isUndefined (ce
)) && !(uentry_isPriv (ce
)) && uentry_isDatatype (ce
));
5305 usymtab_existsTypeEither (cstring k
)
5306 /*@globals globtab@*/
5309 ce
= usymtab_lookupAux (globtab
, k
);
5310 return (uentry_isValid (ce
) && uentry_isDatatype (ce
));
5314 usymtab_existsStructTag (cstring k
) /*@globals globtab@*/
5316 cstring sname
= makeStruct (k
);
5317 uentry ce
= usymtab_lookupAux (globtab
, sname
);
5318 cstring_free (sname
);
5319 return (!(uentry_isUndefined (ce
)) && !(uentry_isPriv (ce
)));
5323 usymtab_existsUnionTag (cstring k
) /*@globals globtab@*/
5325 cstring uname
= makeUnion (k
);
5326 uentry ce
= usymtab_lookupAux (globtab
, uname
);
5328 cstring_free (uname
);
5330 return (!(uentry_isUndefined (ce
)) && !(uentry_isPriv (ce
)));
5334 usymtab_existsEnumTag (cstring k
) /*@globals globtab@*/
5336 cstring ename
= makeEnum (k
);
5337 uentry ce
= usymtab_lookupAux (globtab
, ename
);
5339 cstring_free (ename
);
5340 return (!(uentry_isUndefined (ce
)) && !(uentry_isPriv (ce
)));
5343 bool usymtab_existsVar (cstring k
)
5346 uentry ce
= usymtab_lookupSafe (k
);
5348 return (!(uentry_isUndefined (ce
)) && !(uentry_isPriv (ce
)) && (uentry_isVar (ce
)));
5356 refTable_free (/*@only@*/ /*@null@*/ refTable x
, int nentries
)
5362 for (i
= 0; i
< nentries
; i
++)
5372 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u
)
5373 /*@globals globtab, utab, filetab@*/
5377 DPRINTF (("Free level [%p]", u
));
5378 aliasTable_free (u
->aliases
);
5380 refTable_free (u
->reftable
, u
->nentries
);
5382 if (u
== filetab
|| u
== globtab
)
5384 for (i
= 0; i
< u
->nentries
; i
++)
5386 DPRINTF (("Free complete: %d", i
));
5387 DPRINTF (("Uentry: %s", uentry_unparse (u
->entries
[i
])));
5388 uentry_freeComplete (u
->entries
[i
]);
5389 u
->entries
[i
] = uentry_undefined
;
5394 for (i
= 0; i
< u
->nentries
; i
++)
5396 uentry_free (u
->entries
[i
]);
5397 u
->entries
[i
] = uentry_undefined
;
5401 guardSet_free (u
->guards
);
5408 llassert (!cstringTable_isDefined (u
->htable
));
5411 sfree (u
); /* evans 2002-07-12: was inside if */
5415 usymtab_freeAux (/*@only@*/ usymtab u
)
5416 /*@globals globtab, utab, filetab@*/
5419 while (u
!= GLOBAL_ENV
)
5422 usymtab_freeLevel (u
);
5429 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5431 return (utab
->lexlevel
);
5434 bool usymtab_inGlobalScope (void) /*@globals utab, globtab@*/
5436 return (utab
== globtab
);
5439 bool usymtab_inFileScope (void) /*@globals utab@*/
5441 return (utab
->lexlevel
== fileScope
);
5444 bool usymtab_inFunctionScope (void) /*@globals utab@*/
5446 return (utab
->lexlevel
== functionScope
);
5450 usymtab_replaceEntry (uentry s
)
5451 /*@globals utab, globtab@*/
5452 /*@modifies utab, s@*/
5454 usymtab_replaceEntryAux (utab
, s
);
5458 usymtab_matchForwardStruct (typeId u1
, typeId u2
)
5459 /*@globals globtab@*/
5461 uentry ue1
= usymtab_getTypeEntry (u1
);
5462 uentry ue2
= usymtab_getTypeEntry (u2
);
5464 if (uentry_isAnyTag (ue2
))
5466 ctype reptype
= uentry_getType (ue1
);
5468 if (ctype_isPointer (reptype
))
5470 ctype repbase
= ctype_getBaseType (reptype
);
5472 if (ctype_isUA (repbase
))
5474 typeId rtuid
= ctype_typeId (repbase
);
5476 if (u2
== rtuid
) return TRUE
;
5478 if (typeId_isValid (rtuid
))
5480 reptype
= uentry_getType (usymtab_getTypeEntry (rtuid
));
5481 return (ctype_isUA (reptype
) && (u2
== (ctype_typeId (reptype
))));
5490 void usymtab_addGuards (guardSet guards
)
5493 utab
->guards
= guardSet_union (utab
->guards
, guards
);
5496 static bool usymtab_isGuardedAux (sRef s
)
5500 sRef base
= sRef_getRootBase (s
);
5501 int lowlevel
= paramsScope
;
5502 int baselevel
= sRef_lexLevel (base
);
5504 if (sRef_isCvar (base
))
5506 lowlevel
= baselevel
;
5507 if (lowlevel
< paramsScope
) lowlevel
= paramsScope
;
5510 while (tab
->lexlevel
>= lowlevel
)
5512 DPRINTF (("Is guarded? [%s] %s",
5513 guardSet_unparse (tab
->guards
),
5514 sRef_unparseFull (s
)));
5516 if (guardSet_isGuarded (tab
->guards
, s
))
5519 if (!sRef_definitelyNull (s))
5521 sRef_setNotNull (s, fileloc_undefined);
5527 tab
= usymtab_dropEnv (tab
);
5533 void usymtab_unguard (sRef s
) /*@modifies utab@*/
5536 sRef base
= sRef_getRootBase (s
);
5537 int lowlevel
= paramsScope
;
5538 int baselevel
= sRef_lexLevel (base
);
5540 if (sRef_isCvar (base
))
5542 lowlevel
= baselevel
;
5543 if (lowlevel
< paramsScope
) lowlevel
= paramsScope
;
5546 while (tab
->lexlevel
>= lowlevel
)
5548 if (guardSet_isGuarded (tab
->guards
, s
))
5550 guardSet_delete (tab
->guards
, s
);
5553 tab
= usymtab_dropEnv (tab
);
5557 bool usymtab_isGuarded (sRef s
)
5559 DPRINTF (("Is guarded? %s", sRef_unparseFull (s
)));
5560 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux
, s
));
5563 bool usymtab_isDefinitelyNull (sRef s
)
5565 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux
, s
));
5568 bool usymtab_isDefinitelyNullDeep (sRef s
)
5570 return (sRef_deepPred (usymtab_isDefinitelyNull
, s
));
5573 static bool usymtab_isDefinitelyNullAux (sRef s
)
5577 sRef base
= sRef_getRootBase (s
);
5578 int lowlevel
= paramsScope
;
5580 if (sRef_isCvar (base
))
5582 lowlevel
= sRef_lexLevel (base
);
5583 if (lowlevel
< paramsScope
) lowlevel
= paramsScope
;
5586 while (tab
->lexlevel
>= lowlevel
)
5588 if (guardSet_mustBeNull (tab
->guards
, s
))
5593 while (tab
->kind
== US_CBRANCH
)
5598 llassert (usymtab_isDefined (tab
));
5600 if (tab
->kind
== US_FBRANCH
)
5603 llassert (tab
->kind
== US_TBRANCH
);
5613 usymtab_printGuards (void)
5614 /*@globals utab, globtab@*/
5616 usymtab ttab
= utab
;
5618 while (ttab
!= globtab
)
5620 llmsg (message ("Guards [%d]: %q", ttab
->lexlevel
,
5621 guardSet_unparse (ttab
->guards
)));
5627 usymtab_displayAllUses (void)
5628 /*@globals utab, globtab@*/
5632 /* only in top scope */
5633 llassert (utab
== globtab
);
5635 /* need a copy, so order is not messed up by sort! */
5636 copy
= usymtab_shallowCopy (globtab
);
5638 qsort (copy
->entries
, (size_t)copy
->nentries
,
5639 sizeof (*copy
->entries
), (int (*)(const void *, const void *)) uentry_xcompareuses
);
5641 usymtab_entries (copy
, ue
)
5643 if (uentry_isValid (ue
) && !uentry_isGlobalMarker (ue
))
5645 filelocList uses
= uentry_getUses (ue
);
5646 int size
= filelocList_realSize (uses
);
5648 if (fileloc_isDefined (uentry_whereDefined (ue
))
5649 && !fileloc_isLib (uentry_whereDefined (ue
))
5652 llmsg (message ("%q (%q), %d use%&:\n %q",
5653 uentry_getName (ue
),
5654 fileloc_unparse (uentry_whereDefined (ue
)),
5655 size
, filelocList_unparseUses (uses
)));
5658 } end_usymtab_entries
;
5660 usymtab_shallowFree (copy
);
5663 static /*@dependent@*/ /*@exposed@*/ usymtab
5664 usymtab_getFileTab (void)
5665 /*@globals filetab@*/
5667 llassert (filetab
!= NULL
);
5673 usymtab_unparseStack (void)
5676 return (usymtab_unparseStackTab (utab
));
5679 static /*@only@*/ cstring
5680 usymtab_unparseStackTab (usymtab t
)
5682 bool firstOne
= TRUE
;
5683 cstring ret
= cstring_makeLiteral ("[");
5685 while (t
!= GLOBAL_ENV
)
5689 ret
= message ("%q %q", ret
, usymtab_typeName (t
));
5694 ret
= message ("%q, %q", ret
, usymtab_typeName (t
));
5699 ret
= message ("%q ]", ret
);
5703 static /*@only@*/ cstring
5704 usymtab_typeName (/*@notnull@*/ usymtab t
)
5708 case US_GLOBAL
: return cstring_makeLiteral ("global");
5709 case US_NORMAL
: return cstring_makeLiteral ("normal");
5710 case US_TBRANCH
: return cstring_makeLiteral ("true");
5711 case US_FBRANCH
: return cstring_makeLiteral ("false");
5712 case US_CBRANCH
: return cstring_makeLiteral ("case");
5713 case US_SWITCH
: return cstring_makeLiteral ("switch");
5719 void usymtab_addMustAlias (/*@exposed@*/ sRef s
, /*@exposed@*/ sRef al
)
5722 if (!sRef_similar (s
, al
))
5724 usymtab_addForceMustAlias (s
, al
);
5729 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5732 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s
, /*@exposed@*/ sRef al
)
5735 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5736 if (sRef_isMeaningful (s
)
5737 && sRef_isMeaningful (al
)
5738 && !(sRef_isConst (s
) || sRef_isConst (al
))
5739 && !(sRef_isAddress (al
) && sRef_isDirectParam (sRef_getBase (al
))))
5741 utab
->aliases
= aliasTable_addMustAlias (utab
->aliases
, s
, al
);
5742 DPRINTF (("Must alias: %s", aliasTable_unparse (utab
->aliases
)));
5745 ** for local variable, aliasing is symmetric
5748 if (sRef_isLocalVar (s
) && sRef_isLocalVar (al
))
5750 utab
->aliases
= aliasTable_addMustAlias (utab
->aliases
, al
, s
);
5755 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s
), sRef_unparseFull (al
)));
5756 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s
), sRef_isMeaningful (al
)));
5761 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s
, /*@exposed@*/ sRef al
)
5764 utab
->aliases
= aliasTable_addMustAlias (utab
->aliases
, s
, al
);
5766 # endif /* DEADCODE */
5768 void usymtab_clearAlias (sRef s
)
5769 /*@modifies utab, s@*/
5772 aliasTable_clearAliases (utab
->aliases
, s
);
5775 sRefSet
usymtab_allAliases (sRef s
)
5778 if (sRef_isSomewhatMeaningful (s
))
5782 ret
= sRefSet_unionFree (aliasTable_aliasedBy (utab
->aliases
, s
),
5783 aliasTable_canAlias (utab
->aliases
, s
));
5788 DPRINTF (("NOT A MEANINGFUL SREF!"));
5789 return sRefSet_undefined
;
5793 /*@only@*/ sRefSet
usymtab_canAlias (sRef s
)
5796 if (sRef_isSomewhatMeaningful (s
))
5798 sRefSet res
= aliasTable_canAlias (utab
->aliases
, s
);
5802 return sRefSet_undefined
;
5805 /*@only@*/ sRefSet
usymtab_aliasedBy (sRef s
)
5808 return (aliasTable_aliasedBy (utab
->aliases
, s
));
5811 /*@only@*/ cstring
usymtab_unparseAliases (void)
5814 return (aliasTable_unparse (utab
->aliases
));
5818 ** Debugging routines:
5819 ** okay to leak storage here, only for debugging
5825 usymtab_printOut (void)
5831 char *ind
= mstring_copy (" ");
5833 fprintf (g_warningstream
, "<<< [symbol table] >>>\n");
5835 while (s
!= GLOBAL_ENV
&& s
->env
!= GLOBAL_ENV
)
5837 cstring tname
= usymtab_typeName (s
);
5841 ind
[depth
* 3 + 1] = '\0';
5844 fprintf (g_warningstream
, "level: %d (%s)\n", s
->lexlevel
,
5845 cstring_toCharsSafe (tname
));
5847 cstring_free (tname
);
5849 for (i
= 0; i
< s
->nentries
; i
++)
5851 cstring us
= uentry_unparseFull (s
->entries
[i
]);
5852 fprintf (g_warningstream
, "%s\n", cstring_toCharsSafe (us
));
5856 if (s
->reftable
!= NULL
&& s
->nentries
> 0)
5858 fprintf (g_warningstream
, "\t<< Ref table >>\n");
5860 for (i
= 0; i
< s
->nentries
; i
++)
5862 fprintf (g_warningstream
, "\t%s %3d: %d, %d\n", ind
, i
,
5863 s
->reftable
[i
]->level
,
5864 s
->reftable
[i
]->index
);
5868 ind
[depth
* 3 + 1] = ' ';
5872 fprintf (g_warningstream
, "<<< end usymtab >>>\n");
5878 usymtab_printTypes (void)
5879 /*@globals globtab@*/
5881 usymtab_printAllAux (globtab
);
5885 usymtab_printAll (void)
5888 usymtab_printAllAux (utab
);
5892 usymtab_printAllAux (usymtab s
)
5893 /*@modifies g_warningstream@*/
5897 char *ind
= mstring_copy (" ");
5899 printf ("[[[ usymtab ]]]");
5901 while (s
!= GLOBAL_ENV
)
5904 ind
[depth
* 3 + 1] = '\0';
5906 if (s
->env
== GLOBAL_ENV
)
5910 printf ("level: %d / break: %s / exit: %s\n", s
->lexlevel
,
5911 cstring_toCharsSafe (bool_unparse (s
->mustBreak
)),
5912 cstring_toCharsSafe (exitkind_unparse (s
->exitCode
)));
5916 for (i
= looplow
; i
< s
->nentries
; i
++)
5918 printf ("%s%3d. %s\n", ind
, i
,
5919 cstring_toCharsSafe (uentry_unparseFull (s
->entries
[i
])));
5924 printf ("level: %d / break: %s / exit: %s\n", s
->lexlevel
,
5925 cstring_toCharsSafe (bool_unparse (s
->mustBreak
)),
5926 cstring_toCharsSafe (exitkind_unparse (s
->exitCode
)));
5928 for (i
= 0; i
< s
->nentries
; i
++)
5930 printf ("%s%3d %s\n", ind
, i
,
5931 cstring_toCharsSafe (uentry_unparseFull (s
->entries
[i
])));
5935 ind
[depth
* 3 + 1] = ' ';
5939 printf ("----------\n");
5943 usymtab_printComplete (void)
5948 char *ind
= mstring_copy (" ");
5951 while (s
!= GLOBAL_ENV
)
5955 ind
[depth
* 3 + 1] = '\0';
5958 if (s
->env
== GLOBAL_ENV
)
5962 printf ("level: %d\n", s
->lexlevel
);
5966 for (i
= looplow
; i
< s
->nentries
; i
++)
5968 printf ("%s%3d %s\n", ind
, i
,
5969 cstring_toCharsSafe (uentry_unparseFull (s
->entries
[i
])));
5974 printf ("level: %d\n", s
->lexlevel
);
5975 for (i
= 0; i
< s
->nentries
; i
++)
5977 printf ("%s%3d %s\n", ind
, i
,
5978 cstring_toCharsSafe (uentry_unparseFull (s
->entries
[i
])));
5982 ind
[depth
* 3 + 1] = ' ';
5987 printf ("----------\n");
5992 static /*@only@*/ cstring
/*@unused@*/
5993 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s
)
5995 cstring c
= message ("lexlevel: %d\n", s
->lexlevel
);
5998 for (i
= 0; i
< s
->nentries
; i
++)
6000 c
= message ("%q\n%q", c
, uentry_unparseFull (s
->entries
[i
]));
6003 c
= message ("%q\n=========", c
);
6007 static cstring
/*@unused@*/ /*@only@*/
6008 usymtab_unparseLocalList (/*@notnull@*/ usymtab s
)
6010 cstring c
= message ("[%d/%s/%s] ", s
->lexlevel
,
6011 bool_unparse (s
->mustBreak
),
6012 exitkind_unparse (s
->exitCode
));
6015 for (i
= 0; i
< s
->nentries
; i
++)
6017 sRef sr
= uentry_getSref (s
->entries
[i
]);
6021 c
= message ("%q: %q [%b]", c
, uentry_getName (s
->entries
[i
]),
6022 sRef_isStateDefined (sr
));
6026 c
= message ("%q, %q [%b]", c
, uentry_getName (s
->entries
[i
]),
6027 sRef_isStateDefined (sr
));
6037 usymtab_printLocal (void)
6043 printf ("lexlevel: %d\n", s
->lexlevel
);
6045 for (i
= 0; i
< s
->nentries
; i
++)
6047 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s
->entries
[i
])));
6050 while (s
->lexlevel
> 1)
6055 llassert (usymtab_isDefined (s
));
6057 printf ("Params:\n");
6059 for (i
= 0; i
< s
->nentries
; i
++)
6061 printf ("%d: %s\n", i
,
6062 cstring_toCharsSafe (uentry_unparseFull (s
->entries
[i
])));
6067 static bool checkDistinctExternalName (uentry e
)
6068 /*@globals globtab@*/
6069 /*@modifies *g_warningstream@*/
6071 size_t checklen
= size_fromInt (context_getValue (FLG_EXTERNALNAMELEN
));
6072 bool ignorecase
= context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE
);
6073 bool gotone
= FALSE
;
6074 bool extras
= FALSE
;
6075 bool hasError
= FALSE
;
6076 cstring name
= uentry_rawName (e
);
6077 usymtab st
= globtab
;
6085 if (uentry_isAnyTag (e
))
6087 checklen
++; /* the tag marker doesn't count */
6091 usymtab_entries (st
, oe
)
6093 if (uentry_sameObject (oe
, e
))
6100 if (cstring_equalCaseInsensitive (uentry_rawName (oe
), name
))
6109 (FLG_DISTINCTEXTERNALNAMES
,
6111 ("External identifier %q is not distinguishable from %q "
6112 "because alphabetical case is ignored",
6114 uentry_getName (oe
)),
6115 uentry_whereLast (e
)))
6117 uentry_showWhereAny (oe
);
6118 uentry_setHasNameError (oe
);
6127 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe
),
6136 if (cstring_equalLen (uentry_rawName (oe
), name
, checklen
))
6139 (FLG_DISTINCTEXTERNALNAMES
,
6142 ("External identifier %q is not distinguishable from %q "
6143 "in the first %d characters (%q)",
6145 uentry_getName (oe
),
6146 size_toInt (checklen
),
6147 cstring_clip (uentry_getName (e
), checklen
)),
6149 uentry_whereLast (e
)))
6151 uentry_showWhereAny (oe
);
6152 uentry_setHasNameError (oe
);
6165 (FLG_DISTINCTEXTERNALNAMES
,
6167 ("External identifier %q is not distinguishable from %q "
6168 "in the first %d characters because alphabetical case "
6171 uentry_getName (oe
),
6172 size_toInt (checklen
)),
6173 uentry_whereLast (e
)))
6175 uentry_showWhereAny (oe
);
6176 uentry_setHasNameError (oe
);
6182 else if (cstring_equalLen (uentry_rawName (oe
), name
, checklen
))
6191 (FLG_DISTINCTEXTERNALNAMES
,
6194 ("External identifier %q is not distinguishable from %q "
6195 "in the first %d characters (%q)",
6197 uentry_getName (oe
),
6198 size_toInt (checklen
),
6199 cstring_clip (uentry_getName (e
), checklen
)),
6201 uentry_whereLast (e
)))
6203 uentry_showWhereAny (oe
);
6204 uentry_setHasNameError (oe
);
6213 } end_usymtab_entries
;
6220 (cstring_makeLiteral ("One or more additional "
6221 "indistinguishable external "
6222 "names not reported"));
6228 static bool checkDistinctInternalName (uentry e
)
6230 /*@modifies *g_warningstream@*/
6232 usymtab ttab
= utab
;
6233 cstring name
= uentry_rawName (e
);
6234 size_t numchars
= size_fromInt (context_getValue (FLG_INTERNALNAMELEN
));
6235 bool caseinsensitive
= context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE
);
6236 bool lookalike
= context_getFlag (FLG_INTERNALNAMELOOKALIKE
);
6238 if (uentry_isAnyTag (e
) && (numchars
!= 0))
6240 numchars
++; /* the tag marker doesn't count */
6243 while (usymtab_isDefined (ttab
))
6245 usymtab_entries (ttab
, oe
)
6247 if (uentry_sameObject (oe
, e
))
6249 /*@innercontinue@*/ continue;
6252 switch (cstring_genericEqual
6253 (name
, uentry_rawName (oe
),
6254 numchars
, caseinsensitive
, lookalike
))
6256 case CGE_DISTINCT
: /* okay */
6260 if (cstring_equal (name
, uentry_rawName (oe
)))
6262 ; /* got a shadow error */
6267 (FLG_DISTINCTINTERNALNAMES
,
6270 ("Internal identifier %q is not distinguishable from %q "
6271 "in the first %d characters (%q)",
6273 uentry_getName (oe
),
6274 size_toInt (numchars
),
6275 cstring_clip (uentry_getName (e
), numchars
)),
6277 uentry_whereLast (e
)))
6279 uentry_showWhereAny (oe
);
6280 uentry_setHasNameError (oe
);
6287 if (numchars
== 0 || (cstring_length (name
) <= numchars
))
6290 (FLG_DISTINCTINTERNALNAMES
,
6292 ("Internal identifier %q is not distinguishable from %q "
6293 "without case sensitivity",
6295 uentry_getName (oe
)),
6296 uentry_whereLast (e
)))
6298 uentry_showWhereAny (oe
);
6299 uentry_setHasNameError (oe
);
6306 (FLG_DISTINCTINTERNALNAMES
,
6308 ("Internal identifier %q is not distinguishable from %q "
6309 "in the first %d characters without case sensitivity",
6311 uentry_getName (oe
),
6312 size_toInt (numchars
)),
6313 uentry_whereLast (e
)))
6315 uentry_showWhereAny (oe
);
6316 uentry_setHasNameError (oe
);
6324 || (cstring_length (name
) <= numchars
))
6327 (FLG_DISTINCTINTERNALNAMES
,
6329 ("Internal identifier %q is not distinguishable from %q "
6330 "except by lookalike characters",
6332 uentry_getName (oe
)),
6333 uentry_whereLast (e
)))
6335 uentry_showWhereAny (oe
);
6336 uentry_setHasNameError (oe
);
6343 (FLG_DISTINCTINTERNALNAMES
,
6345 ("Internal identifier %q is not distinguishable from %q "
6346 "in the first %d characters except by lookalike characters",
6348 uentry_getName (oe
),
6349 size_toInt (numchars
)),
6350 uentry_whereLast (e
)))
6352 uentry_showWhereAny (oe
);
6353 uentry_setHasNameError (oe
);
6358 } end_usymtab_entries
;
6366 void usymtab_checkDistinctName (uentry e
, int scope
)
6367 /*@globals utab, globtab@*/
6369 bool hasError
= FALSE
;
6370 fileloc where
= uentry_whereLast (e
);
6372 if (!fileloc_isPreproc (where
) && !fileloc_isBuiltin (where
))
6374 if (scope
== globScope
)
6376 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES
))
6378 hasError
= checkDistinctExternalName (e
);
6382 if (!hasError
&& context_getFlag (FLG_DISTINCTINTERNALNAMES
))
6384 hasError
= checkDistinctInternalName (e
);
6390 uentry_setHasNameError (e
);
6394 /*@exposed@*/ sRef
usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6398 ue
= usymtab_lookupAux (utab
, GLOBAL_MARKER_NAME
);
6399 llassert (uentry_isValid (ue
));
6401 return uentry_getSref (ue
);
6407 ** For debugging only
6411 usymtab_checkAllValid () /*@globals utab@*/
6415 while (tab
!= GLOBAL_ENV
)
6419 for (i
= 0; i
< utab
->nentries
; i
++)
6421 uentry e
= utab
->entries
[i
];
6423 uentry_checkValid (e
);
6426 aliasTable_checkValid (tab
->aliases
);