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
28 # include "splintMacros.nf"
30 # include "structNames.h"
31 # include "nameChecks.h"
33 static /*@dependent@*/ uentry posRedeclared = uentry_undefined;
34 static /*@only@*/ fileloc posLoc = fileloc_undefined;
35 static int nuentries = 0;
36 static int totuentries = 0;
38 static void checkGlobalsModifies (/*@notnull@*/ uentry p_ue, sRefSet p_sr) ;
39 static void uentry_setDeclDef (uentry p_e, fileloc p_f) /*@modifies p_e@*/ ;
40 static bool uentry_isRefCounted (uentry p_ue) /*@*/ ;
41 static bool uentry_isRefsField (uentry p_ue) /*@*/ ;
42 static bool uentry_isReallySpecified (uentry p_e) /*@*/ ;
43 static void uentry_checkIterArgs (uentry p_ue);
44 static cstring uentry_dumpAux (uentry p_v, bool p_isParam);
46 static void uentry_showWhereLastKind (uentry p_spec) /*@modifies g_warningstream@*/ ;
48 static void uentry_combineModifies (uentry p_ue, /*@owned@*/ sRefSet p_sr)
51 static void uentry_addStateClause (uentry p_ue, /*@only@*/ stateClause p_sc)
55 static void checkAliasState (/*@notnull@*/ uentry p_old,
56 /*@notnull@*/ uentry p_unew,
57 bool p_mustConform, bool p_completeConform)
58 /*@modifies p_old, p_unew@*/ ;
59 static void checkNullState (/*@notnull@*/ uentry p_old,
60 /*@notnull@*/ uentry p_unew,
61 bool p_mustConform, bool p_completeConform)
62 /*@modifies p_old, p_unew@*/ ;
64 static void checkVarConformance (/*@notnull@*/ uentry p_old,
65 /*@notnull@*/ uentry p_unew,
66 bool p_mustConform, bool p_completeConform)
67 /*@modifies p_old, p_unew@*/;
69 static void uentry_setHasMods (uentry p_ue) /*@modifies p_ue@*/;
70 static void uentry_setHasGlobs (uentry p_ue) /*@modifies p_ue@*/;
72 static void uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry p_e);
74 static void uentry_setSpecDef (/*@special@*/ uentry p_e, /*@keep@*/ fileloc p_f)
75 /*@defines p_e->whereSpecified, p_e->whereDeclared, p_e->whereDefined@*/
78 static void returnValueError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_unew);
79 static void nargsError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_unew);
80 static /*@observer@*/ cstring paramStorageName (uentry p_ue) /*@*/ ;
81 static /*@observer@*/ cstring fcnErrName (uentry p_ue) /*@*/ ;
82 static /*@observer@*/ cstring checkedName (chkind p_checked) /*@*/ ;
84 paramTypeError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_oldCurrent,
85 ctype p_oldType, /*@notnull@*/ uentry p_unew,
86 /*@notnull@*/ uentry p_newCurrent,
87 ctype p_newType, int p_paramno) /*@modifies g_warningstream@*/ ;
89 static /*@only@*/ /*@notnull@*/ uentry
90 uentry_makeVariableAux (cstring p_n, ctype p_t, /*@keep@*/ fileloc p_f,
91 /*@exposed@*/ sRef p_s, bool p_priv, vkind p_kind);
93 static /*@only@*/ /*@notnull@*/ uentry
94 uentry_makeConstantAux (cstring p_n, ctype p_t,
95 /*@keep@*/ fileloc p_f, bool p_priv, bool p_macro,
96 /*@only@*/ multiVal p_m) /*@*/ ;
98 static void uentry_convertVarFunction (uentry ue) /*@modifies ue@*/
100 if (uentry_isVariable (ue)
101 && (ctype_isFunction (ctype_realType (uentry_getType (ue)))
102 || ctype_isUnknown (uentry_getType (ue))))
104 uentry_makeVarFunction (ue);
108 static /*@out@*/ /*@notnull@*/ uentry uentry_alloc (void) /*@*/
110 uentry ue = (uentry) dmalloc (sizeof (*ue));
111 ue->warn = warnClause_undefined;
118 static cstring uentry_getOptName (uentry p_e) /*@*/ ;
119 static void uentry_updateInto (/*@unique@*/ uentry p_unew, uentry p_old) /*@modifies p_unew, p_old@*/ ;
121 static void uentry_setNullState (/*@notnull@*/ uentry p_ue, nstate p_ns);
122 static void uentry_setAliasKind (/*@notnull@*/ uentry p_ue, alkind p_ak);
123 static /*@only@*/ /*@null@*/ uinfo uinfo_copy (uinfo p_u, ekind p_kind);
124 static void uinfo_free (/*@only@*/ uinfo p_u, ekind p_kind);
125 static void ucinfo_free (/*@only@*/ ucinfo p_u);
126 static void uvinfo_free (/*@only@*/ uvinfo p_u);
130 static /*@only@*/ cstring ancontext_unparse (ancontext an)
134 case AN_UNKNOWN: return cstring_makeLiteral ("unknown");
135 case AN_FCNRETURN: return cstring_makeLiteral ("return value");
136 case AN_FCNPARAM: return cstring_makeLiteral ("function param");
137 case AN_SUFIELD: return cstring_makeLiteral ("su field");
138 case AN_TDEFN: return cstring_makeLiteral ("type definition");
139 case AN_GSVAR: return cstring_makeLiteral ("global/static var");
140 case AN_CONST: return cstring_makeLiteral ("constant");
146 static int annots[AN_LAST][QU_LAST];
147 static int decls[AN_LAST];
148 static int shdecls[AN_LAST];
149 static int idecls[AN_LAST];
155 for (i = AN_UNKNOWN; i < AN_LAST; i++)
161 for (j = QU_UNKNOWN; j < QU_LAST; j++)
168 static void tallyAnnot (ancontext ac, qual q)
182 for (j = QU_UNKNOWN; j < QU_LAST; j++)
187 for (i = AN_UNKNOWN; i < AN_LAST; i++)
193 printf ("Context: %s (%d declarations, %d sharable, %d indirect)\n",
194 ancontext_unparse (i),
195 decls[i], shdecls[i], idecls[i]);
197 totdecls += decls[i];
198 totshdecls += shdecls[i];
199 totidecls += idecls[i];
201 for (j = QU_UNKNOWN; j < QU_LAST; j++)
203 total[j] += annots[i][j];
204 alltotals += annots[i][j];
207 printf (" Allocation:\n");
211 for (j = QU_UNKNOWN; j < QU_LAST; j++)
213 if (qual_isAliasQual (j) && !qual_isUnique (j))
215 if (annots[i][j] > 0)
217 printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
218 100.0 * (double)annots[i][j] / (double)decls[i]);
219 tmptot += annots[i][j];
224 printf (" Exposure:\n");
228 for (j = QU_UNKNOWN; j < QU_LAST; j++)
230 if (qual_isExQual (j))
232 if (annots[i][j] > 0)
234 printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
235 100.0 * (double)annots[i][j] / (double)decls[i]);
236 tmptot += annots[i][j];
241 printf (" Definition:\n");
243 for (j = QU_UNKNOWN; j < QU_LAST; j++)
245 if (qual_isAllocQual (j))
247 if (annots[i][j] > 0)
249 printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
250 100.0 * (double)annots[i][j] / (double)decls[i]);
257 for (j = QU_UNKNOWN; j < QU_LAST; j++)
259 if (qual_isNull (j) || qual_isNotNull (j) || qual_isRelNull (j))
261 if (annots[i][j] > 0)
263 printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
264 100.0 * (double)annots[i][j] / (double)decls[i]);
273 for (j = QU_UNKNOWN; j < QU_LAST; j++)
277 for (i = AN_UNKNOWN; i < AN_LAST; i++)
279 if (annots[i][j] > 0)
288 printf ("Annotation: %s\n", qual_unparse (j));
290 for (i = AN_UNKNOWN; i < AN_LAST; i++)
292 if (annots[i][j] > 0)
294 printf ("%25s: %5d\n", ancontext_unparse (i), annots[i][j]);
301 printf ("All Contexts\n");
303 for (j = QU_UNKNOWN; j < QU_LAST; j++)
307 printf ("%10s: %5d (%3.2f%%)\n", qual_unparse (j), total[j],
308 100.0 * (double)total[j] / (double)(totdecls));
313 printf ("Total Annotations: %d (%d decls, %d sharable, %d indirect)\n", alltotals, totdecls, totshdecls, totidecls); }
315 extern void uentry_tallyAnnots (uentry u, ancontext kind)
317 alkind ak = sRef_getAliasKind (u->sref);
318 exkind ek = sRef_getExKind (u->sref);
319 nstate ns = sRef_getNullState (u->sref);
320 sstate ss = sRef_getDefState (u->sref);
321 bool recordUnknown = FALSE;
323 if (kind == AN_UNKNOWN)
331 else if (e == KCONST || e == KENUMCONST)
335 else if (e == KFCN || e == KITER)
337 uentryList params = uentry_getParams (u);
340 uentryList_elements (params, current)
342 if (uentry_isReturned (current))
346 if (!uentry_isElipsisMarker (current))
348 uentry_tallyAnnots (current, AN_FCNPARAM);
350 } end_uentryList_elements;
354 if (ctype_isFunction (u->utype)
356 && ctype_isVisiblySharable (ctype_realType (ctype_getReturnType (u->utype))))
358 recordUnknown = TRUE;
361 else if (e == KDATATYPE || e == KSTRUCTTAG || e == KUNIONTAG || e == KENUMTAG)
363 ctype t = ctype_realType (u->utype);
367 uentryList fields = ctype_getFields (t);
369 uentryList_elements (fields, current)
371 uentry_tallyAnnots (current, AN_SUFIELD);
373 } end_uentryList_elements;
377 if (ctype_isVisiblySharable (u->utype))
379 recordUnknown = TRUE;
387 if (ctype_isVisiblySharable (ctype_realType (u->utype)))
389 recordUnknown = TRUE;
396 if (kind == AN_FCNRETURN)
410 if (ctype_isVisiblySharable (ctype_realType (u->utype)))
415 if (ctype_isRealPointer (ctype_realType (u->utype)))
423 case SS_ALLOCATED: tallyAnnot (kind, QU_OUT); break;
424 case SS_PARTIAL: tallyAnnot (kind, QU_PARTIAL); break;
425 case SS_RELDEF: tallyAnnot (kind, QU_RELDEF); break;
426 case SS_SPECIAL: tallyAnnot (kind, QU_SPECIAL); break;
430 if (uentry_isReturned (u))
432 tallyAnnot (kind, QU_RETURNED);
438 if (ctype_isRefCounted (ctype_realType (u->utype))
439 || (ctype_isFunction (u->utype) &&
440 ctype_isRefCounted (ctype_realType (ctype_getReturnType (u->utype)))))
446 if (kind == AN_FCNPARAM)
448 tallyAnnot (kind, QU_TEMP);
450 else if (recordUnknown)
452 if (kind == AN_FCNRETURN)
455 tallyAnnot (kind, QU_UNKNOWN);
459 case AK_ONLY: tallyAnnot (kind, QU_ONLY); break;
460 case AK_IMPONLY: tallyAnnot (kind, QU_ONLY); break;
461 case AK_KEEP: tallyAnnot (kind, QU_KEEP); break;
462 case AK_KEPT: tallyAnnot (kind, QU_KEPT); break;
464 case AK_TEMP: tallyAnnot (kind, QU_TEMP); break;
465 case AK_SHARED: tallyAnnot (kind, QU_SHARED); break;
466 case AK_UNIQUE: tallyAnnot (kind, QU_UNIQUE); break;
467 case AK_RETURNED: tallyAnnot (kind, QU_RETURNED); break;
468 case AK_REFCOUNTED: tallyAnnot (kind, QU_UNKNOWN); break;
469 case AK_REFS: tallyAnnot (kind, QU_REFS); break;
470 case AK_KILLREF: tallyAnnot (kind, QU_KILLREF); break;
471 case AK_NEWREF: tallyAnnot (kind, QU_NEWREF); break;
472 case AK_OWNED: tallyAnnot (kind, QU_OWNED); break;
473 case AK_IMPDEPENDENT:
474 case AK_DEPENDENT: tallyAnnot (kind, QU_DEPENDENT); break;
484 case XO_EXPOSED: tallyAnnot (kind, QU_EXPOSED); break;
485 case XO_OBSERVER: tallyAnnot (kind, QU_OBSERVER); break;
491 case NS_ERROR: break;
492 case NS_UNKNOWN: break;
493 case NS_NOTNULL: break;
494 case NS_MNOTNULL: tallyAnnot (kind, QU_NOTNULL); break;
495 case NS_RELNULL: tallyAnnot (kind, QU_RELNULL); break;
496 case NS_CONSTNULL: tallyAnnot (kind, QU_NULL); break;
497 case NS_POSNULL: tallyAnnot (kind, QU_NULL); break;
499 case NS_ABSNULL: break;
505 static /*@observer@*/ cstring specCode_unparse (specCode s) /*@*/
509 case SPC_NONE: return cstring_makeLiteralTemp ("normal");
510 case SPC_PRINTFLIKE: return cstring_makeLiteralTemp ("printflike");
511 case SPC_SCANFLIKE: return cstring_makeLiteralTemp ("scanflike");
512 case SPC_MESSAGELIKE: return cstring_makeLiteralTemp ("messagelike");
513 case SPC_LAST: return cstring_makeLiteralTemp ("<error>");
519 static specCode specCode_fromInt (int i)
522 llassert (i >= SPC_NONE && i < SPC_LAST);
524 return ((specCode) i);
528 /*@observer@*/ cstring uentry_specOrDefName (uentry u)
530 if (uentry_isDeclared (u))
532 return cstring_makeLiteralTemp ("previously declared");
536 return cstring_makeLiteralTemp ("specified");
540 /*@observer@*/ cstring uentry_specDeclName (uentry u)
542 if (uentry_isDeclared (u))
544 return cstring_makeLiteralTemp ("previous declaration");
548 return cstring_makeLiteralTemp ("specification");
552 static /*@observer@*/ cstring uentry_reDefDecl (uentry old, uentry unew) /*@*/
554 if (uentry_isCodeDefined (old) && uentry_isCodeDefined (unew))
556 return cstring_makeLiteralTemp ("redefined");
558 else if (uentry_isCodeDefined (unew))
560 return cstring_makeLiteralTemp ("defined");
562 else if (uentry_isDeclared (old) && uentry_isDeclared (unew))
564 return cstring_makeLiteralTemp ("redeclared");
568 return cstring_makeLiteralTemp ("declared");
572 static constraintList uentry_getFunctionConditions (uentry ue, bool isPost)
574 if (uentry_isValid (ue))
576 functionConstraint constraint;
578 DPRINTF((message ("called uentry_getFcnPostconditions on %s",
579 uentry_unparse (ue) ) ) );
581 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
583 DPRINTF((message ("called uentry_getFunctionConditions on nonfunction %s",
584 uentry_unparse (ue) ) ) );
585 if (!uentry_isFunction (ue) )
587 DPRINTF((message ("called uentry_getFunctionConditions on nonfunction %s",
588 uentry_unparse (ue) ) ));
589 return constraintList_undefined;
593 return constraintList_undefined;
596 if (!uentry_isFunction(ue))
599 DPRINTF((message ("called uentry_getFunctionConditions on non function %s",
600 uentry_unparse (ue) ) ) );
601 return constraintList_undefined;
605 llassert (uentry_isFunction (ue));
609 constraint = ue->info->fcn->postconditions;
613 constraint = ue->info->fcn->preconditions;
616 return functionConstraint_getBufferConstraints (constraint);
619 return constraintList_undefined;
624 /*@only@*/ constraintList uentry_getFcnPreconditions (uentry ue)
626 return uentry_getFunctionConditions (ue, FALSE);
633 constraintList uentry_getFcnPostconditions (uentry ue)
635 return uentry_getFunctionConditions (ue, TRUE);
638 static /*@only@*/ fileloc setLocation (void)
640 fileloc fl = context_getSaveLocation ();
642 if (fileloc_isDefined (fl))
648 return fileloc_copy (g_currentloc);
652 static void uentry_setConstantValue (uentry ue, /*@only@*/ multiVal val)
654 llassert (uentry_isEitherConstant (ue));
655 sRef_setValue (ue->sref, val);
658 /*@notnull@*/ uentry uentry_makeEnumConstant (cstring n, ctype t)
660 fileloc loc = setLocation ();
661 uentry ue = uentry_makeConstant (n, t, loc);
663 ue->ukind = KENUMCONST;
664 uentry_setDefined (ue, loc);
668 /*@notnull@*/ uentry uentry_makeEnumInitializedConstant (cstring n, ctype t, exprNode expr)
670 fileloc loc = setLocation ();
671 uentry ue = uentry_makeConstant (n, t, loc);
672 ctype etype = exprNode_getType (expr);
674 if (!ctype_isRealInt (etype)) {
678 ("Value of enum member is not an integeral type (type %s): %s",
679 ctype_unparse (etype), exprNode_unparse (expr)),
680 exprNode_loc (expr));
683 ue->ukind = KENUMCONST;
684 uentry_setDefined (ue, loc);
688 /*@notnull@*/ uentry uentry_makeSpecEnumConstant (cstring n, ctype t, fileloc loc)
690 uentry ue = uentry_makeConstant (n, t, loc);
692 ue->ukind = KENUMCONST;
696 /*@notnull@*/ uentry uentry_makeVariableLoc (cstring n, ctype t)
698 return uentry_makeVariable (n, t, setLocation (), FALSE);
701 bool uentry_isUnnamedVariable (uentry ue)
703 return uentry_isVariable (ue) && cstring_isUndefined (ue->uname);
706 /*@notnull@*/ /*@only@*/ uentry uentry_makeUnnamedVariable (ctype t)
708 return uentry_makeVariable (cstring_undefined, t, setLocation (), FALSE);
711 /*@notnull@*/ uentry uentry_makeIdDatatype (idDecl id)
713 ctype ct = idDecl_getCtype (id);
714 uentry ue = uentry_makeDatatype (idDecl_observeId (id), ct,
715 MAYBE, qual_createUnknown (),
718 uentry_reflectQualifiers (ue, idDecl_getQuals (id));
720 if (!qual_isEitherAbstract (ue->info->datatype->abs))
722 if (ctype_isUnknown (ct))
724 ue->info->datatype->mut = MAYBE;
728 ue->info->datatype->mut = ynm_fromBool (ctype_isMutable (ct));
735 void uentry_checkParams (uentry ue)
737 if (uentry_isValid (ue))
739 bool isExt = uentry_isExtern (ue);
741 if (uentry_isRealFunction (ue))
743 uentryList params = uentry_getParams (ue);
746 uentryList_elements (params, current)
750 if (uentry_isValid (current))
752 ctype ct = current->utype;
754 if (ctype_isFixedArray (ct))
756 DPRINTF (("Array: %s / %s",
758 ctype_unparse (ctype_baseArrayPtr (ct))));
760 if (ctype_isArray (ctype_baseArrayPtr (ct))
761 && !ctype_isFixedArray (ctype_baseArrayPtr (ct)))
767 if (uentry_hasName (current))
770 (FLG_FIXEDFORMALARRAY,
771 message ("Function parameter %q declared as "
772 "manifest array (size constant is meaningless)",
773 uentry_getName (current)),
774 uentry_whereDeclared (current));
779 (FLG_FIXEDFORMALARRAY,
780 message ("Unnamed function parameter %d declared as "
781 "manifest array (size constant is meaningless)",
783 uentry_whereDeclared (current));
789 if (ctype_isArray (ct))
791 if (uentry_hasName (current))
795 message ("Function parameter %q declared as "
796 "array (treated as pointer)",
797 uentry_getName (current)),
798 uentry_whereDeclared (current));
804 message ("Unnamed function parameter %d declared as "
805 "array (treated as pointer)",
807 uentry_whereDeclared (current));
812 if (sRef_getNullState (uentry_getSref (current)) == NS_MNOTNULL)
814 if (ctype_isAbstract (ct) &&
815 (isExt || (ctype_isAbstract (ctype_realType (ct))
816 && !context_hasFileAccess (ctype_typeId (ct)))))
821 ("Function %q declared with notnull parameter %q of abstract "
824 uentry_getName (current),
827 ("Since %s is an abstract type, notnull can only be "
828 "used for parameters if the function is static to a "
829 "module where %s is accessible.",
832 uentry_whereDeclared (current));
836 } end_uentryList_elements;
838 if (sRef_getNullState (uentry_getSref (ue)) == NS_MNOTNULL)
840 ctype ct = ue->utype;
842 if (ctype_isAbstract (ct)
843 && (isExt || (ctype_isAbstract (ctype_realType (ct))
844 && !context_hasFileAccess (ctype_typeId (ct)))))
849 ("%s %q declared %s notnull storage of abstract type %s",
850 ekind_capName (uentry_getKind (ue)),
855 ("Since %s is an abstract type, notnull can only be used "
856 "if it is static to a module where %s is accessible.",
859 uentry_whereDeclared (ue));
866 static void reflectImplicitFunctionQualifiers (/*@notnull@*/ uentry ue, bool spec)
868 alkind ak = sRef_getAliasKind (ue->sref);
870 if (alkind_isRefCounted (ak))
872 sRef_setAliasKind (ue->sref, AK_NEWREF, fileloc_undefined);
876 if (alkind_isUnknown (ak))
878 exkind ek = sRef_getExKind (ue->sref);
880 if (exkind_isKnown (ek))
882 DPRINTF (("Setting imp dependent: %s",
883 uentry_unparseFull (ue)));
884 sRef_setAliasKind (ue->sref, AK_IMPDEPENDENT, fileloc_undefined);
888 if (context_getFlag (spec ? FLG_SPECRETIMPONLY : FLG_RETIMPONLY))
890 /* evans 2000-12-22 removed ctype_realType so it will
891 not apply to immutable abstract types. */
893 if (ctype_isVisiblySharable
894 (ctype_realType (ctype_getReturnType (ue->utype))))
896 if (uentryList_hasReturned (uentry_getParams (ue)))
902 if (ctype_isImmutableAbstract (ctype_getReturnType (ue->utype))
903 || ctype_isNumAbstract (ctype_getReturnType (ue->utype)))
905 ; /* Immutable objects are not shared. */
909 sRef_setAliasKind (ue->sref, AK_IMPONLY,
911 DPRINTF (("Ret imp only: %s",
912 ctype_unparse (ctype_getReturnType (ue->utype))));
922 static /*@notnull@*/ uentry
923 uentry_makeFunctionAux (cstring n, ctype t,
925 /*@only@*/ globSet globs,
926 /*@only@*/ sRefSet mods,
927 /*@only@*/ warnClause warn,
928 /*@keep@*/ fileloc f, bool priv,
929 /*@unused@*/ bool isForward)
931 uentry e = uentry_alloc ();
934 llassert (warnClause_isUndefined (warn));
936 if (ctype_isFunction (t))
938 ret = ctype_getReturnType (t);
942 if (ctype_isKnown (t))
944 llbug (message ("not function: %s", ctype_unparse (t)));
951 if (fileloc_isSpec (f) || fileloc_isImport (f))
953 e->whereSpecified = f;
954 e->whereDeclared = fileloc_undefined;
958 e->whereSpecified = fileloc_undefined;
959 e->whereDeclared = f;
962 /* e->shallowCopy = FALSE; */
963 e->uname = cstring_copy (n);
965 e->storageclass = SCNONE;
967 e->sref = sRef_makeResult (ret); /* evans 2001-07-19 - was sRef_makeType */
969 DPRINTF (("Result: %s", sRef_unparseFull (e->sref)));
971 if (ctype_isUA (ret))
973 sRef_setStateFromType (e->sref, ret);
978 e->uses = filelocList_new ();
980 e->hasNameError = FALSE;
984 e->info = (uinfo) dmalloc (sizeof (*e->info));
985 e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn));
987 e->info->fcn->hasMods = sRefSet_isDefined (mods);
988 e->info->fcn->hasGlobs = globSet_isDefined (globs);
990 e->info->fcn->exitCode = XK_UNKNOWN;
991 e->info->fcn->nullPred = qual_createUnknown ();
992 e->info->fcn->specialCode = SPC_NONE;
994 e->info->fcn->access = access;
995 e->info->fcn->globs = globs;
996 e->info->fcn->defparams = uentryList_undefined;
998 sRef_setDefined (e->sref, f);
999 e->whereDefined = fileloc_undefined;
1001 e->info->fcn->mods = sRefSet_undefined;
1002 e->info->fcn->specclauses = NULL;
1005 e->info->fcn->preconditions = NULL;
1009 e->info->fcn->postconditions = NULL;
1012 checkGlobalsModifies (e, mods);
1013 e->info->fcn->mods = mods;
1018 static void uentry_reflectClauses (uentry ue, functionClauseList clauses)
1020 functionClauseList_elements (clauses, el)
1022 DPRINTF (("Reflect clause: %s on %s",
1023 functionClause_unparse (el), uentry_getName (ue)));
1025 if (functionClause_isNoMods (el))
1027 modifiesClause mel = functionClause_getModifies (el);
1029 if (uentry_hasGlobs (ue))
1034 ("No globals and modifies inconsistent to globals clause for %q: %q",
1035 uentry_getName (ue),
1036 globSet_unparse (uentry_getGlobs (ue))),
1037 modifiesClause_getLoc (mel));
1041 if (uentry_hasMods (ue))
1046 ("No globals and modifies inconsistent to modifies clause for %q: %q",
1047 uentry_getName (ue),
1048 sRefSet_unparse (uentry_getMods (ue))),
1049 modifiesClause_getLoc (mel));
1052 uentry_setGlobals (ue, globSet_undefined);
1053 uentry_setModifies (ue, sRefSet_undefined);
1055 else if (functionClause_isGlobals (el))
1057 globalsClause glc = functionClause_getGlobals (el);
1059 DPRINTF (("Globals: %s / %s", uentry_unparse (ue),
1060 globalsClause_unparse (glc)));
1062 if (uentry_hasGlobs (ue))
1067 ("Multiple globals clauses for %q: %q",
1068 uentry_getName (ue),
1069 globalsClause_unparse (glc)),
1070 cstring_makeLiteral ("Only one globals clause may be used. The second globals clause is ignored."),
1071 globalsClause_getLoc (glc));
1074 uentry_setGlobals (ue, globalsClause_takeGlobs (glc));
1079 DPRINTF (("Taking globs: %s", globalsClause_unparse (glc)));
1080 uentry_setGlobals (ue, globalsClause_takeGlobs (glc));
1081 DPRINTF (("Taking globs after: %s", globalsClause_unparse (glc)));
1084 else if (functionClause_isModifies (el))
1086 modifiesClause mlc = functionClause_getModifies (el);
1088 DPRINTF (("Has modifies: %s", uentry_unparseFull (ue)));
1090 if (uentry_hasMods (ue))
1098 ("Multiple modifies clauses for %s: %s",
1099 uentry_getName (ue),
1100 modifiesClause_unparse (mlc)),
1101 modifiesClause_getLoc (mlc)))
1103 llhint (message ("Previous modifies clause: ",
1104 sRefSet_unparse (uentry_getMods (ue))));
1110 uentry_combineModifies (ue, modifiesClause_takeMods (mlc));
1114 uentry_setModifies (ue, modifiesClause_takeMods (mlc));
1117 else if (functionClause_isEnsures (el))
1119 functionConstraint cl = functionClause_takeEnsures (el);
1120 DPRINTF (("Setting post: %s / %s",
1121 uentry_unparse (ue), functionConstraint_unparse (cl)));
1122 uentry_setPostconditions (ue, cl);
1124 else if (functionClause_isRequires (el))
1126 functionConstraint cl = functionClause_takeRequires (el);
1127 uentry_setPreconditions (ue, cl);
1129 else if (functionClause_isState (el))
1131 stateClause sc = functionClause_takeState (el);
1133 if (stateClause_isBefore (sc) && stateClause_setsMetaState (sc))
1135 sRefSet rfs = stateClause_getRefs (sc);
1137 sRefSet_elements (rfs, s)
1139 if (sRef_isParam (s))
1142 ** Can't use requires on parameters
1146 (FLG_ANNOTATIONERROR,
1147 message ("Requires clauses for %q concerns parameters %q should be "
1148 "a parameter annotation instead: %q",
1149 uentry_unparse (ue),
1151 stateClause_unparse (sc)),
1152 stateClause_loc (sc));
1154 } end_sRefSet_elements ;
1157 DPRINTF (("State clause: %s", stateClause_unparse (sc)));
1158 uentry_addStateClause (ue, sc);
1160 else if (functionClause_isWarn (el))
1162 warnClause wc = functionClause_takeWarn (el);
1163 uentry_addWarning (ue, wc);
1167 DPRINTF (("Unhandled clause: %s", functionClause_unparse (el)));
1169 } end_functionClauseList_elements ;
1171 DPRINTF (("Checking all: %s", sRef_unparseFull (ue->sref)));
1172 stateClauseList_checkAll (ue);
1175 /*@notnull@*/ uentry uentry_makeIdFunction (idDecl id)
1177 bool leaveFunc = FALSE;
1179 uentry_makeFunction (idDecl_observeId (id), idDecl_getCtype (id),
1180 typeId_invalid, globSet_undefined,
1181 sRefSet_undefined, warnClause_undefined,
1184 DPRINTF (("Id function: %s", sRef_unparseFull (ue->sref)));
1187 ** This makes parameters names print out correctly.
1188 ** (But we might be a local variable declaration for a function type...)
1191 if (context_inFunctionLike ())
1193 DPRINTF (("Header: %s / %s",
1194 uentry_unparse (context_getHeader ()),
1195 idDecl_unparse (id)));
1199 context_enterFunctionDeclaration (ue);
1203 DPRINTF (("Id function: %s", sRef_unparseFull (ue->sref)));
1204 uentry_reflectQualifiers (ue, idDecl_getQuals (id));
1205 DPRINTF (("Id function: %s", sRef_unparseFull (ue->sref)));
1206 reflectImplicitFunctionQualifiers (ue, FALSE);
1207 DPRINTF (("Id function: %s", sRef_unparseFull (ue->sref)));
1208 uentry_reflectClauses (ue, idDecl_getClauses (id));
1209 DPRINTF (("Id function: %s", sRef_unparseFull (ue->sref)));
1211 if (!uentry_isStatic (ue)
1212 && cstring_equalLit (ue->uname, "main"))
1214 ctype typ = ue->utype;
1218 llassert (ctype_isFunction (typ));
1220 retval = ctype_getReturnType (typ);
1222 if (!ctype_isInt (retval))
1226 message ("Function main declared to return %s, should return int",
1227 ctype_unparse (retval)),
1228 uentry_whereDeclared (ue));
1231 args = ctype_argsFunction (typ);
1233 if (uentryList_isMissingParams (args)
1234 || uentryList_size (args) == 0)
1240 if (uentryList_size (args) != 2)
1244 message ("Function main declared with %d arg%&, "
1245 "should have 2 (int argc, char *argv[])",
1246 uentryList_size (args)),
1247 uentry_whereLast (ue));
1251 uentry arg = uentryList_getN (args, 0);
1252 ctype ct = uentry_getType (arg);
1254 if (!ctype_isInt (ct))
1258 message ("Parameter 1, %q, of function main declared "
1259 "with type %t, should have type int",
1260 uentry_getName (arg), ct),
1261 uentry_whereDeclared (arg));
1264 arg = uentryList_getN (args, 1);
1265 ct = uentry_getType (arg);
1267 if (ctype_isArrayPtr (ct)
1268 && ctype_isArrayPtr (ctype_baseArrayPtr (ct))
1269 && ctype_isChar (ctype_baseArrayPtr (ctype_baseArrayPtr (ct))))
1277 message ("Parameter 2, %q, of function main declared "
1278 "with type %t, should have type char **",
1279 uentry_getName (arg), ct),
1280 uentry_whereDeclared (arg));
1288 context_exitFunctionDeclaration ();
1294 static void uentry_implicitParamAnnots (/*@notnull@*/ uentry e)
1296 alkind ak = sRef_getAliasKind (e->sref);
1298 if ((alkind_isUnknown (ak) || alkind_isImplicit (ak))
1299 && context_getFlag (FLG_PARAMIMPTEMP))
1301 exkind ek = sRef_getExKind (e->sref);
1303 if (exkind_isKnown (ek))
1305 DPRINTF (("imp dep: %s", uentry_unparseFull (e)));
1306 sRef_setAliasKind (e->sref, AK_IMPDEPENDENT, fileloc_undefined);
1307 sRef_setOrigAliasKind (e->sref, AK_IMPDEPENDENT);
1311 sRef_setAliasKind (e->sref, AK_IMPTEMP, fileloc_undefined);
1312 sRef_setOrigAliasKind (e->sref, AK_IMPTEMP);
1317 static /*@only@*/ /*@notnull@*/ uentry
1318 uentry_makeVariableParamAux (cstring n, ctype t, /*@dependent@*/ sRef s,
1319 /*@only@*/ fileloc loc, sstate defstate)
1321 cstring pname = makeParam (n);
1324 DPRINTF (("Sref: %s", sRef_unparseFull (s)));
1325 e = uentry_makeVariableAux (pname, t, loc, s, FALSE, VKPARAM);
1327 cstring_free (pname);
1328 DPRINTF (("Param: %s", uentry_unparseFull (e)));
1329 uentry_implicitParamAnnots (e);
1330 DPRINTF (("Param: %s", uentry_unparseFull (e)));
1332 if (!sRef_isAllocated (e->sref) && !sRef_isPartial (e->sref))
1334 DPRINTF (("Param: %s", uentry_unparseFull (e)));
1335 sRef_setDefState (e->sref, defstate, uentry_whereDeclared (e));
1336 e->info->var->defstate = defstate;
1339 DPRINTF (("Param: %s", uentry_unparseFull (e)));
1344 uentry_setRefCounted (uentry e)
1346 if (uentry_isValid (e))
1348 uentry_setAliasKind (e, AK_REFCOUNTED);
1349 sRef_storeState (e->sref);
1354 uentry_setStatic (uentry c)
1356 if (uentry_isValid (c))
1358 alkind ak = sRef_getAliasKind (c->sref);
1359 c->storageclass = SCSTATIC;
1361 if (uentry_isVariable (c) && !ctype_isFunction (uentry_getType (c)))
1363 if (!alkind_isUnknown (ak)
1364 && !alkind_isStatic (ak))
1366 if (!(ctype_isRealPointer (uentry_getType (c)))
1367 && !(ctype_isAbstract (ctype_realType (uentry_getType (c))))
1368 && !alkind_isRefCounted (ak))
1370 if (alkind_isImplicit (ak)
1371 && alkind_isDependent (ak)
1372 && ctype_isArray (uentry_getType (c)))
1374 ; /* no error for observer arrays */
1380 message ("Static storage %q declared as %s",
1382 alkind_unparse (ak)),
1383 uentry_whereDeclared (c));
1389 if (alkind_isUnknown (ak)
1390 || (alkind_isImplicit (sRef_getAliasKind (c->sref))
1391 && !alkind_isDependent (sRef_getAliasKind (c->sref))))
1393 sRef_setAliasKind (c->sref, AK_STATIC, fileloc_undefined);
1394 sRef_setOrigAliasKind (c->sref, AK_STATIC);
1402 uentry_setExtern (uentry c)
1404 if (uentry_isValid (c))
1405 c->storageclass = SCEXTERN;
1409 uentry_setParamNo (uentry ue, int pno)
1411 llassert (uentry_isAnyParam (ue) && sRef_isParam (ue->sref));
1412 sRef_setParamNo (ue->sref, pno);
1416 void checkGlobalsModifies (/*@notnull@*/ uentry ue, sRefSet sr)
1418 sRefSet_allElements (sr, el)
1420 sRef base = sRef_getRootBase (el);
1422 if (sRef_isFileOrGlobalScope (base) || sRef_isInternalState (base)
1423 || (sRef_isKindSpecial (base) && !sRef_isNothing (base)))
1425 if (!globSet_member (ue->info->fcn->globs, base))
1427 if (uentry_hasGlobs (ue)
1428 || context_getFlag (FLG_WARNMISSINGGLOBALSNOGLOBS))
1431 (FLG_WARNMISSINGGLOBALS,
1433 ("Modifies list for %q uses global %q, "
1434 "not included in globals list.",
1435 uentry_getName (ue),
1436 sRef_unparse (base)),
1437 uentry_whereLast (ue)))
1439 uentry_showWhereSpecified (ue);
1443 ue->info->fcn->globs = globSet_insert (ue->info->fcn->globs,
1445 if (sRef_isFileStatic (base))
1447 context_recordFileGlobals (ue->info->fcn->globs);
1451 } end_sRefSet_allElements;
1455 uentry_makeVariableSrefParam (cstring n, ctype t, /*@only@*/ fileloc loc, /*@exposed@*/ sRef s)
1457 return (uentry_makeVariableParamAux (n, t, s, loc, SS_UNKNOWN));
1461 uentry_fixupSref (uentry ue)
1465 if (uentry_isUndefined (ue) || uentry_isElipsisMarker (ue))
1470 sr = uentry_getSref (ue);
1472 sRef_resetState (sr);
1473 sRef_clearDerived (sr);
1475 llassertprint (uentry_isVariable (ue), ("fixing: %s", uentry_unparseFull (ue)));
1476 llassert (sRef_isValid (sr));
1478 if (uentry_isVariable (ue))
1480 /* removed this: no need to copy? ue->sref = sRef_saveCopyShallow (ue->info->var->origsref); */
1481 sRef_setDefState (sr, ue->info->var->defstate, fileloc_undefined);
1482 sRef_setNullState (sr, ue->info->var->nullstate, fileloc_undefined);
1486 static void uentry_addStateClause (/*@notnull@*/ uentry ue, stateClause sc)
1489 ** Okay to allow multiple clauses of the same kind.
1492 ue->info->fcn->specclauses =
1493 stateClauseList_add (ue->info->fcn->specclauses, sc);
1495 /* Will call checkAll to check later... */
1498 void uentry_setStateClauseList (uentry ue, stateClauseList clauses)
1500 llassert (uentry_isFunction (ue));
1501 llassert (!stateClauseList_isDefined (ue->info->fcn->specclauses));
1503 DPRINTF (("checked clauses: %s", stateClauseList_unparse (clauses)));
1504 ue->info->fcn->specclauses = clauses;
1505 stateClauseList_checkAll (ue);
1506 DPRINTF (("checked clauses: %s", uentry_unparseFull (ue)));
1510 ** Used for @modifies@ @endmodifies@ syntax.
1512 ** If ue is specified, sr must contain *only*:
1514 ** o file static globals
1515 ** o sRef's derived from modifies spec (i.e., more specific than
1516 ** what was specified)
1518 ** Otherwise, if sr has modifies it must match sr.
1520 ** If it doesn't have modifies, set them to sr.
1524 uentry_checkModifiesContext (void)
1526 if (sRef_modInFunction ())
1530 ("Modifies list not in function context. "
1531 "A modifies list can only appear following the parameter list "
1532 "in a function declaration or header."));
1541 uentry_setModifies (uentry ue, /*@owned@*/ sRefSet sr)
1543 if (!uentry_checkModifiesContext ())
1549 if (uentry_isValid (ue))
1551 if (uentry_isIter (ue))
1553 llassert (sRefSet_isUndefined (ue->info->iter->mods));
1554 ue->info->iter->mods = sr;
1558 uentry_convertVarFunction (ue);
1559 llassertfatal (uentry_isFunction (ue));
1560 llassert (sRefSet_isUndefined (ue->info->fcn->mods));
1562 ue->info->fcn->mods = sr;
1563 ue->info->fcn->hasMods = TRUE;
1565 checkGlobalsModifies (ue, sr);
1568 if (context_getFlag (FLG_MODIFIESIMPNOGLOBALS))
1570 ue->info->fcn->hasGlobs = TRUE;
1573 if (sRefSet_hasStatic (ue->info->fcn->mods))
1575 context_recordFileModifies (ue->info->fcn->mods);
1585 uentry_combineModifies (uentry ue, /*@owned@*/ sRefSet sr)
1588 ** Function already has one modifies clause (possibly from
1589 ** a specification).
1592 if (!uentry_checkModifiesContext ())
1597 llassert (uentry_isValid (ue));
1599 if (uentry_isIter (ue))
1601 ue->info->iter->mods = sRefSet_unionFree (ue->info->iter->mods, sr);
1605 llassertfatal (uentry_isFunction (ue));
1606 llassert (ue->info->fcn->hasMods);
1608 checkGlobalsModifies (ue, sr);
1609 ue->info->fcn->mods = sRefSet_unionFree (ue->info->fcn->mods, sr);
1611 if (context_getFlag (FLG_MODIFIESIMPNOGLOBALS))
1613 ue->info->fcn->hasGlobs = TRUE;
1617 if (sRefSet_hasStatic (ue->info->fcn->mods))
1619 context_recordFileModifies (ue->info->fcn->mods);
1623 bool uentry_hasWarning (uentry ue)
1625 return (uentry_isValid (ue)
1626 && warnClause_isDefined (ue->warn));
1629 void uentry_addWarning (uentry ue, /*@only@*/ warnClause warn)
1631 llassert (uentry_isValid (ue));
1632 llassert (warnClause_isUndefined (ue->warn));
1637 uentry_setPreconditions (uentry ue, /*@only@*/ functionConstraint preconditions)
1639 if (sRef_modInFunction ())
1642 (message ("Precondition list not in function context. "
1643 "A precondition list can only appear following the parameter list "
1644 "in a function declaration or header."));
1646 /*@-mustfree@*/ return; /*@=mustfree@*/
1649 if (uentry_isValid (ue))
1651 uentry_convertVarFunction (ue);
1652 llassertfatal (uentry_isFunction (ue));
1654 if (functionConstraint_isDefined (ue->info->fcn->preconditions))
1656 /*drl oops this date is wronge...*/
1658 I changed this so it didn't appear as a Splint bug
1659 among other things this gets triggered when there is
1660 a function with two requires clauses. Now Splint
1661 prints an error and tries to conjoin the lists.
1664 (message ("Duplicate precondition list"
1665 "Attemping the conjoin the requires clauses"
1669 /* should conjoin constraints? */
1671 ue->info->fcn->preconditions = functionConstraint_conjoin (ue->info->fcn->preconditions, preconditions);
1675 ue->info->fcn->preconditions = preconditions;
1680 llfatalbug ((message("uentry_setPreconditions called with invalid uentry") ));
1689 uentry_setPostconditions (uentry ue, /*@only@*/ functionConstraint postconditions)
1691 if (sRef_modInFunction ())
1694 (message ("Postcondition list not in function context. "
1695 "A postcondition list can only appear following the parameter list "
1696 "in a function declaration or header."));
1698 /*@-mustfree@*/ return; /*@=mustfree@*/
1701 if (uentry_isValid (ue))
1703 uentry_convertVarFunction (ue);
1704 llassertfatal (uentry_isFunction (ue));
1706 if (functionConstraint_isUndefined (ue->info->fcn->postconditions))
1708 ue->info->fcn->postconditions = postconditions;
1712 ue->info->fcn->postconditions = functionConstraint_conjoin (ue->info->fcn->postconditions, postconditions);
1717 llfatalbug ((message("uentry_setPostconditions called with invalid uentry") ));
1722 ** requires: new and old are functions
1726 checkGlobalsConformance (/*@notnull@*/ uentry old,
1727 /*@notnull@*/ uentry unew,
1728 bool mustConform, bool completeConform)
1730 bool hasInternalState = FALSE;
1732 old->info->fcn->hasGlobs |= unew->info->fcn->hasGlobs;
1734 if (globSet_isDefined (unew->info->fcn->globs))
1736 globSet_allElements (unew->info->fcn->globs, el)
1738 if (sRef_isFileStatic (el))
1740 sRef sr = globSet_lookup (old->info->fcn->globs, el);
1742 if (sRef_isInvalid (sr))
1744 bool hasError = FALSE;
1746 if (!hasInternalState
1747 && sRef_isInvalid (globSet_lookup (old->info->fcn->globs,
1748 sRef_makeInternalState ()))
1749 && sRef_isInvalid (globSet_lookup (old->info->fcn->globs,
1750 sRef_makeSpecState ())))
1753 && !uentry_isStatic (old)
1756 message ("Globals list for %q includes internal state, %q, "
1757 "but %s without globals internalState.",
1758 uentry_getName (old),
1760 uentry_specOrDefName (old)),
1761 uentry_whereLast (unew)))
1763 uentry_showWhereSpecified (old);
1767 old->info->fcn->globs = globSet_insert (old->info->fcn->globs,
1768 sRef_makeInternalState ());
1769 hasInternalState = TRUE;
1773 && fileloc_sameFile (uentry_whereDeclared (unew),
1774 uentry_whereDeclared (old)))
1779 message ("Function %q inconsistently %rdeclared (in "
1780 "same file) with file static global %q in "
1782 uentry_getName (unew),
1783 uentry_isDeclared (old),
1785 uentry_whereDeclared (unew)))
1787 uentry_showWhereSpecified (old);
1792 old->info->fcn->globs = globSet_insert (old->info->fcn->globs, el);
1793 context_recordFileGlobals (old->info->fcn->globs);
1797 sRef sr = globSet_lookup (old->info->fcn->globs, el);
1799 if (sRef_isInvalid (sr))
1804 message ("Function %q inconsistently %rdeclared with "
1805 "%q in globals list",
1806 uentry_getName (unew),
1807 uentry_isDeclared (old),
1809 uentry_whereDeclared (unew)))
1811 old->info->fcn->globs = globSet_insert (old->info->fcn->globs, el);
1812 uentry_showWhereSpecified (old);
1817 if (!bool_equal (sRef_isAllocated (el), sRef_isAllocated (sr)))
1823 ("Function %q global %q inconsistently "
1824 "%rdeclared as %qout global",
1825 uentry_getName (unew),
1827 uentry_isDeclared (old),
1828 cstring_makeLiteral (sRef_isAllocated (el) ? "" : "non-")),
1829 uentry_whereDeclared (unew)))
1831 uentry_showWhereSpecified (old);
1836 } end_globSet_allElements ;
1838 if (completeConform)
1840 globSet_allElements (old->info->fcn->globs, el)
1842 sRef sr = globSet_lookup (unew->info->fcn->globs, el);
1844 if (sRef_isInvalid (sr))
1847 && uentry_isReallySpecified (old)
1850 message ("Function %q specified with %q in globals list, "
1851 "but declared without %q",
1852 uentry_getName (unew),
1855 uentry_whereDeclared (unew)))
1857 uentry_showWhereSpecified (old);
1860 } end_globSet_allElements;
1865 if (completeConform && !globSet_isEmpty (old->info->fcn->globs))
1867 if (uentry_isReallySpecified (old)
1870 message ("%s %q specified with globals list, but "
1871 "declared with no globals",
1872 ekind_capName (unew->ukind),
1873 uentry_getName (unew)),
1874 uentry_whereDeclared (unew)))
1877 (message ("Specification globals: %q",
1878 globSet_unparse (old->info->fcn->globs)),
1879 uentry_whereSpecified (old));
1883 unew->info->fcn->globs = globSet_copyInto (unew->info->fcn->globs,
1884 old->info->fcn->globs);
1889 ** new modifies list must be included by old modifies list.
1891 ** file static state may be added to new, if old has internal.
1895 checkModifiesConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
1896 bool mustConform, bool completeConform)
1899 bool changedMods = FALSE;
1900 bool modInternal = FALSE;
1902 llassert (uentry_isFunction (old) && uentry_isFunction (unew));
1904 old->info->fcn->hasMods |= unew->info->fcn->hasMods;
1905 newMods = unew->info->fcn->mods;
1907 if (sRefSet_isEmpty (newMods))
1909 if (completeConform && !sRefSet_isEmpty (old->info->fcn->mods)
1910 && uentry_isReallySpecified (old))
1914 message ("%s %q specified with modifies clause, "
1915 "but declared with no modifies clause",
1916 ekind_capName (unew->ukind),
1917 uentry_getName (unew)),
1918 uentry_whereDeclared (unew)))
1920 llgenindentmsg (message ("Specification has modifies %q",
1921 sRefSet_unparse (old->info->fcn->mods)),
1922 uentry_whereSpecified (old));
1929 sRefSet_allElements (newMods, current)
1931 if (sRef_isValid (current))
1933 sRef rb = sRef_getRootBase (current);
1935 if (sRef_isFileStatic (rb))
1939 if (!sRefSet_isSameMember (old->info->fcn->mods,
1940 sRef_makeInternalState ())
1941 && !sRefSet_isSameMember (old->info->fcn->mods,
1942 sRef_makeSpecState ()))
1945 && !uentry_isStatic (old)
1949 ("Modifies list for %q includes internal state, "
1950 "but %s without modifies internal.",
1951 uentry_getName (old),
1952 uentry_specOrDefName (old)),
1953 uentry_whereLast (unew)))
1955 uentry_showWhereSpecified (old);
1958 old->info->fcn->mods =
1959 sRefSet_insert (old->info->fcn->mods,
1960 sRef_makeInternalState ());
1965 old->info->fcn->mods = sRefSet_insert (old->info->fcn->mods,
1971 if (sRef_canModifyVal (current, old->info->fcn->mods))
1973 int size = sRefSet_size (old->info->fcn->mods);
1975 old->info->fcn->mods = sRefSet_insert (old->info->fcn->mods,
1978 if (sRefSet_size (old->info->fcn->mods) != size)
1989 ("Modifies list for %q contains %q, not modifiable "
1991 uentry_getName (old),
1992 sRef_unparse (current),
1993 uentry_specDeclName (old)),
1994 uentry_whereLast (unew)))
1996 uentry_showWhereSpecified (old);
2001 } end_sRefSet_allElements;
2003 if (completeConform && uentry_isReallySpecified (old))
2005 sRefSet_allElements (old->info->fcn->mods, el)
2007 if (sRef_canModify (el, newMods))
2016 ("Specification modifies clause for %q contains %q, "
2017 "not included in declaration modifies clause",
2018 uentry_getName (old),
2020 uentry_whereLast (unew)))
2022 uentry_showWhereSpecified (old);
2025 } end_sRefSet_allElements ;
2029 ** Make sure file static elements will be removed.
2034 context_recordFileModifies (old->info->fcn->mods);
2039 uentry_checkMutableType (uentry ue)
2041 ctype ct = uentry_getType (ue);
2043 if (!ctype_isRealPointer (ct) && !ctype_isRealAbstract (ct))
2045 DPRINTF (("Check mutable: %s", uentry_unparseFull (ue)));
2047 voptgenerror (FLG_MUTREP,
2048 message ("Mutable abstract type %q declared without pointer "
2049 "indirection: %t (violates assignment semantics)",
2050 uentry_getName (ue), ct),
2051 uentry_whereDeclared (ue));
2056 uentry_setMutable (uentry e)
2058 llassert (uentry_isDatatype (e));
2059 e->info->datatype->mut = YES;
2063 uentry_checkIterArgs (uentry ue)
2065 bool hasYield = FALSE;
2068 llassert (uentry_isIter (ue));
2070 args = uentry_getParams (ue);
2072 uentryList_elements (args, el)
2074 sstate ds = uentry_getDefState (el);
2076 if (uentry_isYield (el))
2081 if (sstate_isUnknown (ds))
2083 uentry_setDefState (el, SS_DEFINED);
2089 } end_uentryList_elements;
2093 voptgenerror (FLG_HASYIELD,
2094 message ("Iterator %q declared with no yield parameters",
2095 uentry_getName (ue)),
2096 uentry_whereDeclared (ue));
2101 chkind_fromQual (qual qel)
2103 if (qual_isChecked (qel))
2107 else if (qual_isCheckMod (qel))
2111 else if (qual_isCheckedStrict (qel))
2113 return CH_CHECKEDSTRICT;
2115 else if (qual_isUnchecked (qel))
2117 return CH_UNCHECKED;
2122 /*@notreached@*/ return CH_UNKNOWN;
2127 uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel)
2129 if (qual_isKillRef (qel) || qual_isNewRef (qel) || qual_isTempRef (qel))
2131 if (!uentry_isRefCounted (ue))
2134 (FLG_ANNOTATIONERROR,
2135 message ("Reference counting qualifier %s used on non-reference "
2136 "counted storage: %q",
2138 uentry_unparse (ue)),
2139 uentry_whereLast (ue));
2143 alkind ak = alkind_fromQual (qel);
2145 uentry_setAliasKind (ue, ak);
2148 else if (qual_isRefCounted (qel))
2150 ctype ct = ctype_realType (uentry_getType (ue));
2153 if (ctype_isPointer (ct)
2154 && (ctype_isStruct (rt = ctype_realType (ctype_baseArrayPtr (ct)))))
2156 /* check there is a refs field */
2157 uentryList fields = ctype_getFields (rt);
2158 uentry refs = uentry_undefined;
2160 uentryList_elements (fields, field)
2162 if (uentry_isRefsField (field))
2164 if (uentry_isValid (refs))
2167 (FLG_ANNOTATIONERROR,
2168 message ("Reference counted structure type %s has "
2169 "multiple refs fields: %q and %q",
2171 uentry_getName (refs),
2172 uentry_getName (field)),
2173 uentry_whereLast (field));
2178 } end_uentryList_elements;
2180 if (uentry_isInvalid (refs))
2184 message ("Reference counted structure type %s has "
2186 ctype_unparse (ct)),
2188 ("To count reference, the structure must have a field named "
2189 "refs of type int."),
2192 else if (!ctype_isInt (uentry_getType (refs)))
2195 (FLG_ANNOTATIONERROR,
2196 message ("Reference counted structure type %s refs field has "
2197 "type %s (should be int)", ctype_unparse (ct),
2198 ctype_unparse (uentry_getType (refs))),
2199 uentry_whereLast (refs));
2203 sRef_setAliasKind (ue->sref, alkind_fromQual (qel),
2204 uentry_whereDeclared (ue));
2209 if ((ctype_isPointer (ct)
2210 && ctype_isUnknown (ctype_realType (ctype_baseArrayPtr (ct))))
2211 ||ctype_isAbstract (ct) || ctype_isUnknown (ct))
2213 sRef_setAliasKind (ue->sref, alkind_fromQual (qel),
2214 uentry_whereDeclared (ue));
2219 (FLG_ANNOTATIONERROR,
2220 message ("Non-pointer to structure type %s declared with "
2221 "refcounted qualifier",
2222 ctype_unparse (ct)),
2223 uentry_whereLast (ue));
2227 else if (qual_isRefs (qel))
2229 if (uentry_isVariable (ue) && !uentry_isParam (ue))
2231 uentry_setAliasKind (ue, AK_REFS);
2236 (FLG_ANNOTATIONERROR,
2237 message ("Refs qualifier used on non-structure field: %q",
2238 uentry_unparse (ue)),
2239 uentry_whereLast (ue));
2242 else if (qual_isAliasQual (qel))
2244 alkind ak = alkind_fromQual (qel);
2246 alkind oldak = uentry_getAliasKind (ue);
2247 ctype ut = uentry_getType (ue);
2249 if (alkind_isImplicit (ak)
2250 && (alkind_isKnown (oldak) && !alkind_isImplicit (oldak)))
2252 /* ignore the implied qualifier */
2256 if (uentry_isEitherConstant (ue))
2259 (FLG_ANNOTATIONERROR,
2260 message ("Alias qualifier %s used on constant: %q",
2261 alkind_unparse (ak), uentry_unparse (ue)),
2262 uentry_whereLast (ue));
2267 if (ctype_isFunction (ut))
2269 ut = ctype_getReturnType (ut);
2272 if (!(ctype_isVisiblySharable (ut)
2273 || ctype_isRealArray (ut)
2274 || ctype_isRealSU (ut)))
2276 if (!qual_isImplied (qel))
2279 (FLG_ANNOTATIONERROR,
2280 message ("Alias qualifier %s used on unsharable storage type %t: %q",
2281 alkind_unparse (ak), ut, uentry_getName (ue)),
2282 uentry_whereLast (ue));
2289 if (uentry_isRefCounted (ue))
2291 if (!(qual_isRefQual (qel) || qual_isOnly (qel)
2292 || qual_isExposed (qel)
2293 || qual_isObserver (qel)))
2295 if (!qual_isImplied (qel))
2298 (FLG_ANNOTATIONERROR,
2300 ("Alias qualifier %s used on reference counted storage: %q",
2301 alkind_unparse (ak),
2302 uentry_unparse (ue)),
2303 uentry_whereLast (ue));
2311 if (qual_isRefQual (qel))
2314 (FLG_ANNOTATIONERROR,
2315 message ("Qualifier %s used on non-reference counted storage: %q",
2316 alkind_unparse (ak), uentry_unparse (ue)),
2317 uentry_whereLast (ue));
2326 uentry_setAliasKind (ue, ak);
2329 else if (qual_isNull (qel))
2331 if (uentry_isConstant (ue))
2335 ctype_isAbstract (ue->utype) ? NS_CONSTNULL : NS_DEFNULL,
2336 uentry_whereDeclared (ue));
2340 uentry_setNullState (ue, NS_POSNULL);
2343 else if (qual_isRelNull (qel))
2345 uentry_setNullState (ue, NS_RELNULL);
2347 else if (qual_isNotNull (qel))
2349 uentry_setNullState (ue, NS_MNOTNULL);
2351 else if (qual_isAbstract (qel)
2352 || qual_isNumAbstract (qel)
2353 || qual_isConcrete (qel))
2355 if (!uentry_isDatatype (ue))
2358 (FLG_ANNOTATIONERROR,
2359 message ("Qualifier %s used with non-datatype",
2360 qual_unparse (qel)),
2361 uentry_whereLast (ue));
2365 ue->info->datatype->abs = qel;
2366 DPRINTF (("Setting abstract %s: %s",
2367 uentry_unparse (ue), qual_unparse (qel)));
2370 else if (qual_isMutable (qel))
2372 if (!uentry_isDatatype (ue))
2375 (FLG_ANNOTATIONERROR,
2376 message ("Qualifier %s used with non-datatype", qual_unparse (qel)),
2377 uentry_whereLast (ue));
2381 if (!ynm_isOn (ue->info->datatype->mut))
2383 uentry_checkMutableType (ue);
2386 ue->info->datatype->mut = YES;
2389 else if (qual_isImmutable (qel))
2391 if (!uentry_isDatatype (ue))
2393 voptgenerror (FLG_ANNOTATIONERROR,
2394 message ("Qualifier %s used with non-datatype",
2395 qual_unparse (qel)),
2396 uentry_whereLast (ue));
2400 ue->info->datatype->mut = NO;
2403 else if (qual_isNullPred (qel))
2405 uentry_convertVarFunction (ue);
2407 if (uentry_isFunction (ue))
2409 ctype typ = uentry_getType (ue);
2410 ctype rtype = ctype_getReturnType (uentry_getType (ue));
2412 if (ctype_isRealBool (rtype))
2414 uentryList pl = ctype_argsFunction (typ);
2416 if (uentryList_size (pl) == 1)
2418 ue->info->fcn->nullPred = qel;
2422 voptgenerror (FLG_ANNOTATIONERROR,
2423 message ("Qualifier %s used with function having %d "
2424 "arguments (should have 1)",
2426 uentryList_size (pl)),
2427 uentry_whereLast (ue));
2432 voptgenerror (FLG_ANNOTATIONERROR,
2433 message ("Qualifier %s used with function returning %s "
2434 "(should return bool)",
2436 ctype_unparse (rtype)),
2437 uentry_whereLast (ue));
2442 voptgenerror (FLG_ANNOTATIONERROR,
2443 message ("Qualifier %s used with non-function",
2444 qual_unparse (qel)),
2445 uentry_whereLast (ue));
2448 else if (qual_isExitQual (qel))
2450 exitkind exk = exitkind_fromQual (qel);
2452 if (uentry_isFunction (ue))
2454 if (exitkind_isKnown (ue->info->fcn->exitCode))
2456 voptgenerror (FLG_ANNOTATIONERROR,
2457 message ("Multiple exit qualifiers used on function %q: %s, %s",
2458 uentry_getName (ue),
2459 exitkind_unparse (ue->info->fcn->exitCode),
2460 exitkind_unparse (exk)),
2461 uentry_whereLast (ue));
2464 ue->info->fcn->exitCode = exk;
2468 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2470 uentry_makeVarFunction (ue);
2471 ue->info->fcn->exitCode = exk;
2475 voptgenerror (FLG_ANNOTATIONERROR,
2476 message ("Exit qualifier %s used with non-function (type %s)",
2478 ctype_unparse (uentry_getType (ue))),
2479 uentry_whereLast (ue));
2483 else if (qual_isMetaState (qel))
2485 annotationInfo ainfo = qual_getAnnotationInfo (qel);
2487 if (annotationInfo_matchesContext (ainfo, ue))
2489 DPRINTF (("Reflecting %s on %s",
2490 annotationInfo_unparse (ainfo),
2491 uentry_unparseFull (ue)));
2493 sRef_reflectAnnotation (ue->sref, ainfo, g_currentloc);
2494 DPRINTF (("==> %s", sRef_unparseFull (ue->sref)));
2495 DPRINTF (("==> %s", uentry_unparseFull (ue)));
2500 (FLG_ANNOTATIONERROR,
2501 message ("Attribute annotation %s used in inconsistent context: %q",
2503 uentry_unparse (ue)),
2504 uentry_whereLast (ue)))
2506 /* annotationInfo_showContextError (ainfo, ue); */
2512 if (qual_isCQual (qel))
2518 llbug (message ("Unhandled qualifier: %s", qual_unparse (qel)));
2524 uentry_reflectQualifiers (uentry ue, qualList q)
2526 llassert (uentry_isValid (ue));
2528 DPRINTF (("Reflect qualifiers: %s / %s",
2529 uentry_unparseFull (ue), qualList_unparse (q)));
2531 qualList_elements (q, qel)
2533 if (qual_isStatic (qel))
2535 uentry_setStatic (ue);
2537 else if (qual_isUnused (qel))
2539 uentry_setUsed (ue, fileloc_undefined);
2540 DPRINTF (("Used: %s", uentry_unparseFull (ue)));
2542 else if (qual_isExternal (qel))
2544 fileloc_free (ue->whereDefined);
2545 ue->whereDefined = fileloc_createExternal ();
2547 else if (qual_isSef (qel))
2549 if (uentry_isVariable (ue))
2551 vkind vk = ue->info->var->kind;
2553 llassert (vk != VKREFPARAM);
2555 if (vk == VKYIELDPARAM)
2558 (FLG_ANNOTATIONERROR,
2559 message ("Qualifier sef cannot be used with %s: %q",
2560 cstring_makeLiteralTemp (vk == VKYIELDPARAM ? "yield" : "returned"),
2561 uentry_unparse (ue)),
2562 uentry_whereLast (ue));
2564 else if (vk == VKRETPARAM)
2566 ue->info->var->kind = VKSEFRETPARAM;
2570 ue->info->var->kind = VKSEFPARAM;
2576 (FLG_ANNOTATIONERROR,
2577 message ("Qualifier sef is meaningful only on parameters: %q",
2578 uentry_unparse (ue)),
2579 uentry_whereLast (ue));
2582 else if (qual_isExtern (qel))
2584 ue->storageclass = SCEXTERN;
2586 else if (qual_isGlobalQual (qel)) /* undef, killed */
2588 DPRINTF (("Reflecting qual: %s / %s",
2589 qual_unparse (qel), uentry_unparse (ue)));
2591 if (uentry_isVariable (ue))
2593 sstate oldstate = ue->info->var->defstate;
2594 sstate defstate = sstate_fromQual (qel);
2597 if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
2598 || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
2600 defstate = SS_UNDEFKILLED;
2607 sRef_setDefState (ue->sref, defstate, fileloc_undefined);
2608 ue->info->var->defstate = defstate;
2613 (FLG_ANNOTATIONERROR,
2614 message ("Qualifier %s used on non-variable: %q",
2615 qual_unparse (qel), uentry_unparse (ue)),
2616 uentry_whereLast (ue));
2619 DPRINTF (("After: %s", uentry_unparseFull (ue)));
2621 /* start modifications */
2622 else if( qual_isBufQualifier(qel) ) {
2623 ctype ct = ctype_realType(uentry_getType(ue));
2624 if( ctype_isArray(ct) || ctype_isPointer(ct) ) {
2626 if( uentry_hasBufStateInfo(ue) ) {
2627 if( qual_isNullTerminated(qel) ) { /* handle Nullterm */
2629 if (uentry_isAnyParam(ue) || uentry_isReturned (ue)) {
2630 /* If formal func param */
2631 uentry_setNullTerminatedState(ue);
2632 uentry_setLen (ue, 1);
2633 uentry_setSize (ue, 1);
2635 sRef_setNullTerminatedState(uentry_getSref(ue));
2636 sRef_setLen (uentry_getSref(ue), 1);
2637 sRef_setSize (uentry_getSref(ue), 1);
2639 uentry_setPossiblyNullTerminatedState(ue);
2641 sRef_setPossiblyNullTerminatedState(uentry_getSref(ue));
2645 /* put other BufState Qualifiers here */
2647 cstring s = uentry_getName(ue);
2648 llfatalbug(message("INTERNAL Error: we have a NULL BufState \
2649 struct for identifier %s\n", s) );
2651 } else if (ctype_isFunction (ct)) { /* We have to handle function */
2653 sRef retSref = uentry_getSref (ue);
2654 ctype retType = sRef_getType (retSref);
2656 if (ctype_isPointer (retType) || ctype_isArray (retType)) {
2657 sRef_setNullTerminatedState (retSref);
2663 message ("Qualifier %s used on non-pointer on \
2664 function return: %q", qual_unparse (qel),
2665 uentry_unparse (ue)));
2672 message ("Qualifier %s used on non-pointer: %q",
2673 qual_unparse (qel), uentry_unparse (ue)));
2675 DPRINTF (("After: %s", uentry_unparseFull (ue)));
2677 else if (qual_isAllocQual (qel)) /* out, partial, reldef, special, etc. */
2679 ctype realType = ctype_realType (ue->utype);
2680 sstate defstate = sstate_fromQual (qel);
2682 if (ctype_isFunction (realType))
2684 realType = ctype_realType (ctype_getReturnType (realType));
2687 if (qual_isRelDef (qel))
2689 ; /* okay anywhere */
2693 if (!ctype_isAP (realType)
2694 && !ctype_isSU (realType)
2695 && !ctype_isUnknown (realType)
2696 && !ctype_isAbstract (ue->utype))
2699 (FLG_ANNOTATIONERROR,
2700 message ("Qualifier %s used on non-pointer or struct: %q",
2701 qual_unparse (qel), uentry_unparse (ue)),
2702 uentry_whereLast (ue));
2706 uentry_setDefState (ue, defstate);
2708 if (sRef_isStateSpecial (ue->sref)
2709 && alkind_isImplicit (sRef_getAliasKind (ue->sref)))
2711 sRef_setAliasKind (ue->sref, AK_ERROR, fileloc_undefined);
2714 else if (qual_isYield (qel))
2716 if (uentry_isVariable (ue))
2718 ue->info->var->kind = VKYIELDPARAM;
2723 (FLG_ANNOTATIONERROR,
2724 message ("Qualifier %s used on non-iterator parameter: %q",
2725 qual_unparse (qel), uentry_unparse (ue)),
2726 uentry_whereLast (ue));
2729 else if (qual_isExQual (qel))
2731 exkind ek = exkind_fromQual (qel);
2732 ctype ut = uentry_getType (ue);
2734 DPRINTF (("Reflect ex qual: %s / %s",
2735 uentry_unparse (ue), exkind_unparse (ek)));
2737 if (ctype_isFunction (ut))
2739 ut = ctype_getReturnType (ut);
2742 if (!(ctype_isVisiblySharable (ut))
2743 && !(ctype_isArray (ut)) /* can apply to arrays also! */
2744 && !(ctype_isStruct (ctype_realType (ut)))) /* applies to structure fields! */
2746 if (!qual_isImplied (qel))
2748 if (ctype_isImmutableAbstract (ut)) {
2750 (FLG_REDUNDANTSHAREQUAL,
2751 message ("Qualifier %s used on unsharable storage type %t: %q",
2752 exkind_unparse (ek), ut, uentry_getName (ue)),
2753 uentry_whereLast (ue));
2756 (FLG_MISPLACEDSHAREQUAL,
2757 message ("Qualifier %s used on unsharable storage type %t: %q",
2758 exkind_unparse (ek), ut, uentry_getName (ue)),
2759 uentry_whereLast (ue));
2765 alkind ak = sRef_getAliasKind (ue->sref);
2767 sRef_setExKind (ue->sref, ek, uentry_whereDeclared (ue));
2768 DPRINTF (("Set exkind: %s", sRef_unparseFull (ue->sref)));
2770 if (alkind_isUnknown (ak) || alkind_isImplicit (ak) || alkind_isStatic (ak))
2772 if (!alkind_isTemp (ak))
2774 DPRINTF (("imp dep: %s", uentry_unparseFull (ue)));
2775 uentry_setAliasKind (ue, AK_IMPDEPENDENT);
2778 else if (alkind_isDependent (ak) || alkind_isTemp (ak)
2779 || alkind_isOwned (ak))
2787 message ("Exposure qualifier %s used on %s storage (should "
2788 "be dependent): %q",
2790 alkind_unparse (ak),
2791 uentry_unparse (ue)));
2795 else if (qual_isGlobCheck (qel))
2797 if (uentry_isVariable (ue))
2799 chkind ch = chkind_fromQual (qel);
2801 if (ue->info->var->checked != CH_UNKNOWN)
2803 if (ch == ue->info->var->checked)
2805 llerror (FLG_SYNTAX,
2806 message ("Redundant %s qualifier on %q",
2808 uentry_getName (ue)));
2812 llerror (FLG_SYNTAX,
2814 ("Contradictory %s and %s qualifiers on %q",
2816 checkedName (ue->info->var->checked),
2817 uentry_getName (ue)));
2821 ue->info->var->checked = ch;
2827 message ("Qualifier %s used with non-variable",
2828 qual_unparse (qel)));
2831 else if (qual_isReturned (qel))
2833 if (uentry_isVariable (ue))
2835 ue->info->var->kind = VKRETPARAM;
2839 llerror (FLG_SYNTAX, message ("Qualifier %s used with non-variable",
2840 qual_unparse (qel)));
2845 uentry_reflectOtherQualifier (ue, qel);
2848 sRef_storeState (ue->sref);
2849 } end_qualList_elements;
2853 DPRINTF (("Done: %s", sRef_unparseFull (ue->sref)));
2857 uentry_isOnly (uentry ue)
2859 return (!uentry_isUndefined (ue)
2860 && uentry_isVariable (ue)
2861 && alkind_isOnly (sRef_getOrigAliasKind (ue->sref)));
2865 uentry_setAliasKind (/*@notnull@*/ uentry ue, alkind ak)
2867 sRef_setAliasKind (ue->sref, ak, uentry_whereDeclared (ue));
2868 sRef_setOrigAliasKind (ue->sref, ak);
2872 uentry_setNullState (/*@notnull@*/ uentry ue, nstate ns)
2874 if (uentry_isVariable (ue))
2876 ue->info->var->nullstate = ns;
2879 sRef_setNullState (ue->sref, ns, uentry_whereDeclared (ue));
2883 uentry_isUnique (uentry ue)
2885 return (!uentry_isUndefined (ue)
2886 && uentry_isVariable (ue)
2887 && alkind_isUnique (sRef_getOrigAliasKind (ue->sref)));
2891 uentry_isFileStatic (uentry ue)
2893 return (uentry_isStatic (ue)
2894 && (!uentry_isVariable (ue)
2895 || sRef_isFileStatic (uentry_getSref (ue))));
2899 uentry_isExported (uentry ue)
2901 if (uentry_isValid (ue))
2903 if (uentry_isVariable (ue))
2905 return (sRef_isRealGlobal (uentry_getSref (ue)));
2909 return !uentry_isStatic (ue);
2917 uentry_isNonLocal (uentry ue)
2919 return (uentry_isValid (ue) && uentry_isVariable (ue)
2920 && (sRef_isFileOrGlobalScope (ue->sref) || uentry_isStatic (ue)));
2924 uentry_isGlobalVariable (uentry ue)
2926 return (uentry_isValid (ue) && uentry_isVariable (ue)
2927 && sRef_isFileOrGlobalScope (ue->sref));
2931 uentry_isVisibleExternally (uentry ue)
2933 return (uentry_isValid (ue)
2934 && ((uentry_isVariable (ue) && sRef_isRealGlobal (ue->sref))
2935 || (!uentry_isStatic (ue)
2936 && (uentry_isFunction (ue)
2937 || uentry_isIter (ue)
2938 || uentry_isEndIter (ue)
2939 || uentry_isConstant (ue)
2940 || uentry_isDatatype (ue)
2941 || uentry_isAnyTag (ue)))));
2945 uentry_isPrintfLike (uentry ue)
2947 return (uentry_isFunction (ue)
2948 && (ue->info->fcn->specialCode == SPC_PRINTFLIKE));
2952 uentry_isScanfLike (uentry ue)
2954 return (uentry_isFunction (ue)
2955 && (ue->info->fcn->specialCode == SPC_SCANFLIKE));
2959 uentry_isMessageLike (uentry ue)
2961 return (uentry_isFunction (ue)
2962 && (ue->info->fcn->specialCode == SPC_MESSAGELIKE));
2965 static void checkSpecialFunction (/*@notnull@*/ uentry ue)
2967 uentryList args = uentry_getParams (ue);
2969 if (!uentryList_isMissingParams (args))
2971 uentry last = uentry_undefined;
2973 uentryList_elements (args, current)
2975 if (uentry_isElipsisMarker (current))
2977 if (uentry_isUndefined (last))
2981 message ("Function %q is marked %s, but has no format "
2982 "string argument before elipsis",
2983 uentry_getName (ue),
2984 specCode_unparse (ue->info->fcn->specialCode)),
2985 uentry_whereLast (ue));
2986 ue->info->fcn->specialCode = SPC_NONE;
2990 ctype rt = ctype_realType (uentry_getType (last));
2992 if (!ctype_match (rt, ctype_string))
2996 /* wchar_t * is okay too */
2997 if (ctype_isAP (rt))
2999 ctype base = ctype_baseArrayPtr (rt);
3001 if (ctype_isArbitraryIntegral (base))
3011 message ("Function %q is marked %s, but the argument "
3012 "before the elipsis has type %s (should be char *)",
3013 uentry_getName (ue),
3014 specCode_unparse (ue->info->fcn->specialCode),
3015 ctype_unparse (uentry_getType (last))),
3016 uentry_whereLast (ue));
3018 ue->info->fcn->specialCode = SPC_NONE;
3025 } end_uentryList_elements ;
3029 message ("Function %q is marked %s, but has no elipsis parameter",
3030 uentry_getName (ue),
3031 specCode_unparse (ue->info->fcn->specialCode)),
3032 uentry_whereLast (ue));
3034 ue->info->fcn->specialCode = SPC_NONE;
3039 uentry_setPrintfLike (uentry ue)
3041 uentry_convertVarFunction (ue);
3042 llassertfatal (uentry_isFunction (ue));
3043 ue->info->fcn->specialCode = SPC_PRINTFLIKE;
3044 checkSpecialFunction (ue);
3048 uentry_setScanfLike (uentry ue)
3050 uentry_convertVarFunction (ue);
3051 llassertfatal (uentry_isFunction (ue));
3052 ue->info->fcn->specialCode = SPC_SCANFLIKE;
3053 checkSpecialFunction (ue);
3057 uentry_setMessageLike (uentry ue)
3059 uentry_convertVarFunction (ue);
3060 llassertfatal (uentry_isFunction (ue));
3061 ue->info->fcn->specialCode = SPC_MESSAGELIKE;
3062 checkSpecialFunction (ue);
3066 uentry_isSpecialFunction (uentry ue)
3068 return (uentry_isFunction (ue)
3069 && (ue->info->fcn->specialCode != SPC_NONE));
3072 /*@notnull@*/ uentry uentry_makeParam (idDecl t, int i)
3074 ctype ct = idDecl_getCtype (t);
3075 fileloc loc = setLocation ();
3076 sRef pref = sRef_makeParam (i, ct, stateInfo_makeLoc (loc, SA_CREATED));
3077 uentry ue = uentry_makeVariableSrefParam (idDecl_observeId (t), ct, loc, pref);
3079 DPRINTF (("Make param: %s", uentry_unparseFull (ue)));
3080 DPRINTF (("Base: %s [%d]", ctype_unparse (ct), ctype_isFixedArray (ct)));
3081 uentry_reflectQualifiers (ue, idDecl_getQuals (t));
3082 uentry_implicitParamAnnots (ue);
3084 if (ctype_isArray (ct))
3086 /* Parameter type [][] or [x][] is invalid, but [][x] is okay */
3087 ctype base = ctype_baseArrayPtr (ct);
3089 DPRINTF (("Check array: %s / Base: %s", ctype_unparse (ct),
3090 ctype_unparse (base)));
3092 if (ctype_isIncompleteArray (base))
3094 if (!uentry_hasName (ue))
3097 (FLG_INCOMPLETETYPE,
3098 message ("Unnamed function parameter %d is incomplete type "
3099 "(inner array must have bounds): %s",
3101 ctype_unparse (ct)),
3102 uentry_whereLast (ue));
3107 (FLG_INCOMPLETETYPE,
3108 message ("Function parameter %q is incomplete type "
3109 "(inner array must have bounds): %s",
3110 uentry_getName (ue),
3111 ctype_unparse (ct)),
3112 uentry_whereLast (ue));
3117 DPRINTF (("Param: %s", uentry_unparseFull (ue)));
3121 /*@only@*/ /*@notnull@*/ uentry uentry_makeIdVariable (idDecl t)
3123 ctype ct = idDecl_getCtype (t);
3125 if (ctype_isFunction (ct))
3127 return (uentry_makeIdFunction (t));
3131 fileloc loc = setLocation ();
3132 uentry ue = uentry_makeVariable (idDecl_observeId (t), ct, loc, FALSE);
3134 uentry_reflectQualifiers (ue, idDecl_getQuals (t));
3136 if (!uentry_isExtern (ue))
3138 uentry_setDefined (ue, loc);
3145 /*@notnull@*/ uentry uentry_makeVariableParam (cstring n, ctype t, fileloc loc)
3147 return (uentry_makeVariableParamAux (n, t, sRef_makeType (t), fileloc_copy (loc), SS_DEFINED));
3154 static /*@only@*/ /*@notnull@*/
3155 uentry uentry_makeConstantAux (cstring n, ctype t,
3156 /*@keep@*/ fileloc f, bool priv, bool macro,
3157 /*@only@*/ multiVal m)
3159 uentry e = uentry_alloc ();
3162 e->uname = cstring_copy (n);
3164 e->storageclass = SCNONE;
3166 e->warn = warnClause_undefined; /* Don't support warnings for constants */
3168 e->sref = sRef_makeConst (t);
3173 e->uses = filelocList_new ();
3174 e->isPrivate = priv;
3175 e->hasNameError = FALSE;
3177 e->info = (uinfo) dmalloc (sizeof (*e->info));
3178 e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
3179 e->info->uconst->access = typeIdSet_undefined;
3180 e->info->uconst->macro = macro;
3182 uentry_setSpecDef (e, f);
3184 if (multiVal_isInt (m) && (multiVal_forceInt (m) == 0))
3186 sRef_setDefNull (e->sref, uentry_whereDeclared (e));
3189 uentry_setConstantValue (e, m);
3194 /*@notnull@*/ uentry uentry_makeConstant (cstring n, ctype t, fileloc f)
3196 uentry ue = uentry_makeConstantAux (n, t, f, FALSE, FALSE, multiVal_unknown ());
3200 /*@notnull@*/ uentry uentry_makeConstantValue (cstring n, ctype t, fileloc f, bool priv, multiVal val)
3202 uentry ue = uentry_makeConstantAux (n, t, f, priv, FALSE, val);
3206 /*@notnull@*/ uentry uentry_makeMacroConstant (cstring n, ctype t, fileloc f)
3208 uentry ue = uentry_makeConstantAux (n, t, f, FALSE, TRUE, multiVal_unknown ());
3212 /*@notnull@*/ uentry uentry_makeIdConstant (idDecl t)
3214 uentry ue = uentry_makeConstant (idDecl_observeId (t),
3215 idDecl_getCtype (t),
3218 llassert (fileloc_isUndefined (ue->whereDeclared));
3219 ue->whereDeclared = setLocation ();
3220 uentry_reflectQualifiers (ue, idDecl_getQuals (t));
3222 DPRINTF (("Constant: %s", uentry_unparseFull (ue)));
3223 DPRINTF (("Value: %s", multiVal_unparse (uentry_getConstantValue (ue))));
3231 void uentry_setDefState (uentry ue, sstate defstate)
3233 if (uentry_isValid (ue))
3235 sRef_setDefState (ue->sref, defstate, fileloc_undefined);
3237 if (uentry_isVariable (ue))
3239 ue->info->var->defstate = defstate; /* evs 2000-05-17: fixed bug, was SS_DEFINED! */
3244 bool uentry_isCheckedUnknown (uentry ue)
3246 return (uentry_isVar (ue)
3247 && (ue->info->var->checked == CH_UNKNOWN));
3250 bool uentry_isCheckMod (uentry ue)
3252 return (uentry_isVar (ue)
3253 && (ue->info->var->checked == CH_CHECKMOD));
3256 bool uentry_isUnchecked (uentry ue)
3258 return (uentry_isVar (ue)
3259 && (ue->info->var->checked == CH_UNCHECKED));
3262 bool uentry_isChecked (uentry ue)
3264 return (uentry_isVar (ue)
3265 && (ue->info->var->checked == CH_CHECKED));
3268 bool uentry_isCheckedModify (uentry ue)
3270 return (uentry_isVar (ue)
3271 && (ue->info->var->checked == CH_CHECKED
3272 || ue->info->var->checked == CH_CHECKMOD
3273 || ue->info->var->checked == CH_CHECKEDSTRICT));
3276 bool uentry_isCheckedStrict (uentry ue)
3278 return (uentry_isVar (ue)
3279 && (ue->info->var->checked == CH_CHECKEDSTRICT));
3282 void uentry_setUnchecked (uentry ue)
3284 llassert (uentry_isVar (ue));
3286 ue->info->var->checked = CH_UNCHECKED;
3289 void uentry_setChecked (uentry ue)
3291 llassert (uentry_isVar (ue));
3293 ue->info->var->checked = CH_CHECKED;
3296 void uentry_setCheckMod (uentry ue)
3298 llassert (uentry_isVar (ue));
3300 ue->info->var->checked = CH_CHECKMOD;
3303 void uentry_setCheckedStrict (uentry ue)
3305 llassert (uentry_isVar (ue));
3307 ue->info->var->checked = CH_CHECKEDSTRICT;
3310 static /*@only@*/ /*@notnull@*/
3311 uentry uentry_makeVariableAux (cstring n, ctype t,
3313 /*@exposed@*/ sRef s,
3314 bool priv, vkind kind)
3316 uentry e = uentry_alloc ();
3319 DPRINTF (("Make variable: %s %s %s", n, ctype_unparse (t), sRef_unparse (s)));
3322 e->uname = cstring_copy (n);
3325 e->storageclass = SCNONE;
3327 e->warn = warnClause_undefined; /* Don't support warnings for variables yet @*/
3334 e->uses = filelocList_new ();
3335 e->isPrivate = priv;
3336 e->hasNameError = FALSE;
3338 e->info = (uinfo) dmalloc (sizeof (*e->info));
3339 e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
3340 e->info->var->kind = kind;
3342 /* removed: e->info->var->origsref = sRef_saveCopy (e->sref); */
3343 e->info->var->checked = CH_UNKNOWN;
3345 DPRINTF (("Here we are: %s", sRef_unparseFull (e->sref)));
3346 uentry_setSpecDef (e, f);
3347 DPRINTF (("Here we are: %s", sRef_unparseFull (e->sref)));
3349 if (ctype_isFunction (rt))
3351 rt = ctype_getReturnType (rt);
3354 if (ctype_isUA (rt))
3356 DPRINTF (("Here we are: %s", sRef_unparseFull (e->sref)));
3357 sRef_setStateFromType (e->sref, rt);
3360 e->info->var->defstate = sRef_getDefState (e->sref);
3361 e->info->var->nullstate = sRef_getNullState (e->sref);
3363 /* start modifications */
3364 /* This function sets the uentry for a pointer or array variable declaration,
3365 it allocates memory and sets the fields. We check if the type of the variable
3366 is a pointer or array and allocate a `bbufinfo' struct accordingly */
3368 if (ctype_isArray (t) || ctype_isPointer(t))
3370 e->info->var->bufinfo = dmalloc (sizeof (*e->info->var->bufinfo));
3371 e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED;
3372 sRef_setNotNullTerminatedState (s);
3376 e->info->var->bufinfo = NULL;
3378 /* end modification */
3380 DPRINTF (("New variable: %s", sRef_unparseFull (e->sref)));
3386 uentry_isYield (uentry ue)
3388 return (uentry_isVariable (ue)
3389 && (ue->info->var->kind == VKYIELDPARAM
3390 || ue->info->var->kind == VKREFYIELDPARAM));
3394 uentry_isRefsField (uentry ue)
3396 return (uentry_isVariable (ue) && sRef_isRefsField (ue->sref));
3399 /*@only@*/ /*@notnull@*/
3400 uentry uentry_makeVariable (cstring n, ctype t, fileloc f, bool isPriv)
3402 return (uentry_makeVariableAux (n, t, f, sRef_makeType (t), isPriv,
3403 fileloc_isSpec (f) ? VKSPEC : VKNORMAL));
3410 void uentry_makeVarFunction (uentry ue)
3417 llassert (uentry_isValid (ue));
3418 llassert (!sRef_modInFunction ());
3420 ak = sRef_getOrigAliasKind (ue->sref);
3421 ek = sRef_getOrigExKind (ue->sref);
3423 llassert (uentry_isVariable (ue));
3424 oldInfo = ue->info->var;
3426 DPRINTF (("ue: %s", uentry_unparseFull (ue)));
3427 llassert (ctype_isUnknown (ue->utype) || ctype_isFunction (ctype_realType (ue->utype)));
3430 ** expanded macro is marked used
3433 ue->used = ue->used || (oldInfo->kind == VKEXPMACRO);
3436 ue->info->fcn = (ufinfo) dmalloc (sizeof (*ue->info->fcn));
3437 ue->info->fcn->exitCode = XK_UNKNOWN;
3438 ue->info->fcn->nullPred = qual_createUnknown ();
3439 ue->info->fcn->specialCode = SPC_NONE;
3440 ue->info->fcn->access = typeIdSet_undefined;
3441 ue->info->fcn->hasGlobs = FALSE;
3442 ue->info->fcn->globs = globSet_undefined;
3443 ue->info->fcn->hasMods = FALSE;
3444 ue->info->fcn->mods = sRefSet_undefined;
3445 ue->info->fcn->specclauses = NULL;
3446 ue->info->fcn->defparams = uentryList_undefined;
3449 ue->info->fcn->preconditions = functionConstraint_undefined;
3453 ue->info->fcn->postconditions = functionConstraint_undefined;
3456 if (ctype_isFunction (ue->utype))
3458 ue->sref = sRef_makeType (ctype_getReturnType (ue->utype));
3462 ue->sref = sRef_makeType (ctype_unknown);
3465 if (sRef_isRefCounted (ue->sref))
3471 if (alkind_isUnknown (ak))
3473 if (exkind_isKnown (ek))
3475 DPRINTF (("imp dep: %s", uentry_unparseFull (ue)));
3476 ak = AK_IMPDEPENDENT;
3480 if (context_getFlag (FLG_RETIMPONLY))
3482 if (ctype_isFunction (ue->utype)
3483 && ctype_isVisiblySharable
3484 (ctype_realType (ctype_getReturnType (ue->utype))))
3486 if (uentryList_hasReturned (uentry_getParams (ue)))
3492 if (ctype_isImmutableAbstract (ctype_getReturnType (ue->utype)))
3507 loc = ue->whereDeclared;
3509 sRef_setAliasKind (ue->sref, ak, loc);
3510 sRef_setNullState (ue->sref, oldInfo->nullstate, loc);
3511 sRef_setDefState (ue->sref, oldInfo->defstate, loc);
3512 sRef_setExKind (ue->sref, ek, loc);
3514 if (oldInfo->kind == VKEXPMACRO)
3520 fileloc_free (ue->whereDefined);
3521 ue->whereDefined = fileloc_undefined;
3524 uvinfo_free (oldInfo);
3527 void uentry_makeConstantFunction (uentry ue)
3534 llassert (uentry_isValid (ue));
3535 llassert (!sRef_modInFunction ());
3537 ak = sRef_getOrigAliasKind (ue->sref);
3538 ek = sRef_getOrigExKind (ue->sref);
3540 llassert (uentry_isConstant (ue));
3541 oldInfo = ue->info->uconst;
3543 llassert (ctype_isUnknown (ue->utype) || ctype_isFunction (ue->utype));
3546 ** expanded macro is marked used (until I write a pre-processor)
3550 ue->info->fcn = (ufinfo) dmalloc (sizeof (*ue->info->fcn));
3551 ue->info->fcn->exitCode = XK_UNKNOWN;
3552 ue->info->fcn->nullPred = qual_createUnknown ();
3553 ue->info->fcn->specialCode = SPC_NONE;
3554 ue->info->fcn->access = typeIdSet_undefined;
3555 ue->info->fcn->hasGlobs = FALSE;
3556 ue->info->fcn->globs = globSet_undefined;
3557 ue->info->fcn->hasMods = FALSE;
3558 ue->info->fcn->mods = sRefSet_undefined;
3559 ue->info->fcn->specclauses = NULL;
3560 ue->info->fcn->defparams = uentryList_undefined;
3563 ue->info->fcn->preconditions = functionConstraint_undefined;
3567 ue->info->fcn->postconditions = functionConstraint_undefined;
3571 if (ctype_isFunction (ue->utype))
3573 ue->sref = sRef_makeType (ctype_getReturnType (ue->utype));
3577 ue->sref = sRef_makeType (ctype_unknown);
3580 if (sRef_isRefCounted (ue->sref))
3586 if (alkind_isUnknown (ak))
3588 if (exkind_isKnown (ek))
3590 DPRINTF (("imp dep: %s", uentry_unparseFull (ue)));
3591 ak = AK_IMPDEPENDENT;
3595 if (context_getFlag (FLG_RETIMPONLY))
3597 if (ctype_isFunction (ue->utype)
3598 && ctype_isVisiblySharable
3599 (ctype_realType (ctype_getReturnType (ue->utype))))
3601 if (uentryList_hasReturned (uentry_getParams (ue)))
3607 if (ctype_isImmutableAbstract (ctype_getReturnType (ue->utype)))
3622 loc = ue->whereDeclared;
3624 sRef_setAliasKind (ue->sref, ak, loc);
3625 sRef_setExKind (ue->sref, ek, loc);
3627 fileloc_free (ue->whereDefined);
3628 ue->whereDefined = fileloc_undefined;
3629 ucinfo_free (oldInfo);
3633 uentry_setGlobals (uentry ue, /*@only@*/ globSet globs)
3635 llassert (uentry_isValid (ue));
3637 globSet_markImmutable (globs);
3639 if (uentry_isIter (ue))
3641 ue->info->iter->globs = globSet_unionFree (ue->info->iter->globs, globs);
3645 uentry_convertVarFunction (ue);
3646 llassert (uentry_isFunction (ue));
3648 ue->info->fcn->hasGlobs = TRUE;
3649 ue->info->fcn->globs = globSet_unionFree (ue->info->fcn->globs, globs);
3652 if (context_getFlag (FLG_GLOBALSIMPMODIFIESNOTHING))
3654 ue->info->fcn->hasMods = TRUE;
3658 void uentry_addAccessType (uentry ue, typeId tid)
3660 if (uentry_isFunction (ue))
3662 ue->info->fcn->access = typeIdSet_insert (ue->info->fcn->access, tid);
3664 else if (uentry_isEitherConstant (ue))
3666 ue->info->uconst->access = typeIdSet_insert (ue->info->uconst->access, tid);
3668 else if (uentry_isIter (ue))
3670 ue->info->iter->access = typeIdSet_insert (ue->info->iter->access, tid);
3672 else if (uentry_isEndIter (ue))
3674 ue->info->enditer->access = typeIdSet_insert (ue->info->enditer->access, tid);
3678 llbug (message ("no access for: %q", uentry_unparse (ue)));
3682 /*@only@*/ /*@notnull@*/ uentry
3683 uentry_makeFunction (cstring n, ctype t,
3685 /*@only@*/ globSet globs, /*@only@*/ sRefSet mods,
3686 /*@only@*/ warnClause warn,
3689 llassert (warnClause_isUndefined (warn));
3690 return (uentry_makeFunctionAux (n, t,
3691 ((typeId_isInvalid (access)) ? typeIdSet_emptySet ()
3692 : typeIdSet_single (access)),
3698 /*@notnull@*/ uentry
3699 uentry_makePrivFunction2 (cstring n, ctype t,
3701 globSet globs, sRefSet mods,
3704 return (uentry_makeFunctionAux (n, t, access, globs, mods, warnClause_undefined,
3709 /*@notnull@*/ uentry
3710 uentry_makeSpecFunction (cstring n, ctype t,
3712 /*@only@*/ globSet globs,
3713 /*@only@*/ sRefSet mods,
3716 uentry ue = uentry_makeFunctionAux (n, t, access,
3717 globs, mods, warnClause_undefined,
3720 uentry_setHasGlobs (ue);
3721 uentry_setHasMods (ue);
3723 reflectImplicitFunctionQualifiers (ue, TRUE);
3727 uentry uentry_makeExpandedMacro (cstring s, fileloc f)
3729 uentry ue = uentry_makeVariableAux (s, ctype_unknown, fileloc_undefined,
3730 sRef_undefined, FALSE, VKEXPMACRO);
3732 uentry_setDefined (ue, f);
3736 /*@notnull@*/ /*@notnull@*/ uentry
3737 uentry_makeForwardFunction (cstring n, typeId access, fileloc f)
3739 uentry ue = uentry_makeFunctionAux (n, ctype_unknown,
3740 typeIdSet_singleOpt (access),
3741 globSet_undefined, sRefSet_undefined,
3742 warnClause_undefined,
3746 ue->whereDeclared = fileloc_update (ue->whereDeclared, f);
3750 bool uentry_isForward (uentry e)
3752 if (uentry_isValid (e))
3754 ctype ct = uentry_getType (e);
3756 return (ctype_isUnknown (ct)
3757 || (ctype_isFunction (ct)
3758 && ctype_isUnknown (ctype_getReturnType (ct))));
3764 /*@notnull@*/ uentry
3765 uentry_makeTypeListFunction (cstring n, typeIdSet access, fileloc f)
3767 return (uentry_makeFunctionAux (n, ctype_unknown, access,
3768 globSet_undefined, sRefSet_undefined, warnClause_undefined,
3772 /*@notnull@*/ uentry
3773 uentry_makeUnspecFunction (cstring n, ctype t,
3777 uentry ue = uentry_makeFunctionAux (n, t, access, globSet_undefined,
3778 sRefSet_undefined, warnClause_undefined,
3781 reflectImplicitFunctionQualifiers (ue, TRUE);
3789 /* is exported for use by usymtab_interface */
3791 /*@notnull@*/ uentry
3792 uentry_makeDatatypeAux (cstring n, ctype t, ynm mut, qual abstract,
3793 fileloc f, bool priv)
3795 uentry e = uentry_alloc ();
3797 DPRINTF (("Make datatype: %s / %s",
3798 n, ctype_unparse (t)));
3800 /* e->shallowCopy = FALSE; */
3801 e->ukind = KDATATYPE;
3802 e->uname = cstring_copy (n);
3804 e->storageclass = SCNONE;
3805 e->sref = sRef_makeUnknown ();
3809 sRef_setStateFromType (e->sref, t);
3812 uentry_setSpecDef (e, f);
3814 e->warn = warnClause_undefined;
3815 e->uses = filelocList_new ();
3816 e->isPrivate = priv;
3817 e->hasNameError = FALSE;
3822 e->info = (uinfo) dmalloc (sizeof (*e->info));
3823 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3824 e->info->datatype->abs = abstract;
3825 e->info->datatype->mut = mut;
3826 e->info->datatype->type = ctype_undefined;
3828 if (uentry_isDeclared (e))
3830 uentry_setDefined (e, f);
3833 if (qual_isAbstract (abstract) && !(uentry_isCodeDefined (e)))
3835 sRef_setNullState (e->sref, NS_ABSNULL, uentry_whereDeclared (e));
3841 /*@notnull@*/ uentry
3842 uentry_makeDatatype (cstring n, ctype t, ynm mut, qual abstract, fileloc f)
3844 return (uentry_makeDatatypeAux (n, t, mut, abstract, f, FALSE));
3847 /*@notnull@*/ uentry uentry_makeBoolDatatype (qual abstract)
3849 uentry ret = uentry_makeDatatypeAux (context_getBoolName (),
3850 ctype_bool, NO, abstract,
3851 fileloc_getBuiltin (),
3854 ret->info->datatype->type = ctype_bool;
3862 static /*@only@*/ /*@notnull@*/ uentry
3863 uentry_makeIterAux (cstring n, typeIdSet access, ctype ct,
3864 /*@only@*/ fileloc f)
3866 uentry e = uentry_alloc ();
3869 e->uname = cstring_copy (n);
3871 e->sref = sRef_makeUnknown ();
3872 e->storageclass = SCNONE;
3876 uentry_setSpecDef (e, f);
3878 e->warn = warnClause_undefined;
3879 e->uses = filelocList_new ();
3880 e->isPrivate = FALSE;
3881 e->hasNameError = FALSE;
3883 e->info = (uinfo) dmalloc (sizeof (*e->info));
3884 e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
3885 e->info->iter->access = access;
3886 e->info->iter->mods = sRefSet_undefined;
3887 e->info->iter->globs = globSet_undefined;
3889 uentry_checkIterArgs (e);
3893 /*@notnull@*/ uentry uentry_makeIter (cstring n, ctype ct, fileloc f)
3895 return (uentry_makeIterAux (n, context_fileAccessTypes (), ct, f));
3898 static /*@notnull@*/ uentry
3899 uentry_makeEndIterAux (cstring n, typeIdSet access, /*@only@*/ fileloc f)
3901 uentry e = uentry_alloc ();
3903 /* e->shallowCopy = FALSE; */
3904 e->ukind = KENDITER;
3905 e->storageclass = SCNONE;
3906 e->uname = message ("end_%s", n);
3907 e->utype = ctype_unknown;
3908 e->sref = sRef_makeUnknown ();
3910 uentry_setSpecDef (e, f);
3915 e->uses = filelocList_new ();
3916 e->isPrivate = FALSE;
3917 e->hasNameError = FALSE;
3919 e->info = (uinfo) dmalloc (sizeof (*e->info));
3920 e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
3922 e->info->enditer->access = access;
3923 e->warn = warnClause_undefined;
3928 /*@notnull@*/ /*@only@*/ uentry uentry_makeEndIter (cstring n, fileloc f)
3930 return (uentry_makeEndIterAux (n, context_fileAccessTypes (), f));
3937 static /*@only@*/ /*@notnull@*/ uentry
3938 uentry_makeTagAux (cstring n, ctype t,
3939 /*@only@*/ fileloc fl,
3940 bool priv, ekind kind)
3942 uentry e = uentry_alloc ();
3944 if (kind != KSTRUCTTAG && kind != KUNIONTAG && kind != KENUMTAG)
3946 llbuglit ("uentry_makeTagAux: not a tag type");
3950 /* e->shallowCopy = FALSE; */
3951 e->uname = cstring_copy (n);
3954 e->sref = sRef_makeUnknown ();
3955 e->storageclass = SCNONE;
3957 uentry_setSpecDef (e, fl);
3962 e->uses = filelocList_new ();
3963 e->isPrivate = priv;
3964 e->hasNameError = FALSE;
3966 e->info = (uinfo) dmalloc (sizeof (*e->info));
3967 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3968 e->info->datatype->abs = qual_createUnknown ();
3969 e->info->datatype->mut = (kind == KENUMTAG) ? NO : MAYBE;
3970 e->info->datatype->type = t;
3971 e->warn = warnClause_undefined;
3973 if (uentry_isDeclared (e))
3975 uentry_setDefined (e, fl);
3981 uentry uentry_makeStructTagLoc (cstring n, ctype t)
3983 cstring sname = makeStruct (n);
3984 uentry ret = uentry_makeTagAux (sname, t, setLocation (), FALSE, KSTRUCTTAG);
3986 cstring_free (sname);
3991 uentry_makeStructTag (cstring n, ctype t, fileloc loc)
3993 cstring sname = makeStruct (n);
3994 uentry ret = uentry_makeTagAux (sname, t, loc, FALSE, KSTRUCTTAG);
3996 cstring_free (sname);
4001 uentry_makeUnionTag (cstring n, ctype t, fileloc loc)
4003 cstring uname = makeUnion (n);
4004 uentry ret = uentry_makeTagAux (uname, t, loc, FALSE, KUNIONTAG);
4006 cstring_free (uname);
4011 uentry_makeEnumTag (cstring n, ctype t, fileloc loc)
4013 cstring ename = makeEnum (n);
4014 uentry ret = uentry_makeTagAux (ename, t, loc, FALSE, KENUMTAG);
4016 cstring_free (ename);
4021 uentry_makeUnionTagLoc (cstring n, ctype t)
4023 cstring uname = makeUnion (n);
4024 uentry ret = uentry_makeTagAux (uname, t, setLocation (), FALSE, KUNIONTAG);
4026 cstring_free (uname);
4031 uentry_makeEnumTagLoc (cstring n, ctype t)
4033 cstring ename = makeEnum (n);
4034 uentry ret = uentry_makeTagAux (ename, t, setLocation (), FALSE, KENUMTAG);
4036 cstring_free (ename);
4041 uentry_isStructTag (uentry ue)
4043 return (uentry_isValid (ue) && ue->ukind == KSTRUCTTAG);
4047 uentry_isUnionTag (uentry ue)
4049 return (uentry_isValid (ue) && ue->ukind == KUNIONTAG);
4053 uentry_isEnumTag (uentry ue)
4055 return (uentry_isValid (ue) && ue->ukind == KENUMTAG);
4059 uentry_isAnyTag (uentry ue)
4061 return (uentry_isStructTag (ue)
4062 || uentry_isUnionTag (ue)
4063 || uentry_isEnumTag (ue));
4066 static /*@unchecked@*/ /*@only@*/ uentry emarker = NULL;
4068 extern void uentry_destroyMod (void)
4069 /*@globals killed emarker@*/ /*@modifies emarker@*/
4071 static bool wasDestroyed = FALSE;
4073 llassert (!wasDestroyed);
4075 if (emarker != NULL)
4077 uentry_reallyFree (emarker);
4080 wasDestroyed = TRUE;
4084 uentry_makeElipsisMarker (void)
4086 if (emarker == NULL)
4088 emarker = uentry_alloc ();
4090 emarker->ukind = KELIPSMARKER;
4091 emarker->uname = cstring_makeLiteral ("...");
4092 emarker->utype = ctype_elipsMarker;
4093 emarker->sref = sRef_undefined;
4094 emarker->storageclass = SCNONE;
4095 emarker->used = FALSE;
4096 emarker->lset = FALSE;
4097 emarker->info = NULL;
4099 uentry_setSpecDef (emarker, fileloc_undefined);
4100 emarker->uses = filelocList_new ();
4101 emarker->isPrivate = FALSE;
4102 emarker->hasNameError = FALSE;
4105 /*@ignore@*/ return (emarker); /*@end@*/
4113 uentry_equiv (uentry p1, uentry p2)
4115 if (uentry_compare (p1, p2) != 0)
4126 uentry_xcomparealpha (uentry *p1, uentry *p2)
4130 if ((res = uentry_compare (*p1, *p2)) == 0) {
4131 if ((*p1 != NULL) && (*p2 != NULL)) {
4132 res = cstring_compare ((*p1)->uname,
4141 uentry_xcompareuses (uentry *p1, uentry *p2)
4146 if (uentry_isValid (u1))
4148 if (uentry_isValid (u2))
4150 return (-1 * int_compare (filelocList_size (u1->uses),
4151 filelocList_size (u2->uses)));
4160 if (uentry_isValid (u2))
4172 uentry_compareStrict (uentry v1, uentry v2)
4174 COMPARERETURN (uentry_compare (v1, v2));
4176 if (v1 != v2 && uentry_isValid (v1) && uentry_isValid (v2))
4178 COMPARERETURN (fileloc_compare (v1->whereDeclared, v2->whereDeclared));
4179 COMPARERETURN (fileloc_compare (v1->whereDefined, v2->whereDefined));
4180 COMPARERETURN (fileloc_compare (v1->whereSpecified, v2->whereSpecified));
4187 uentry_compare (uentry u1, uentry u2)
4189 if (u1 == u2) return 0;
4191 if (uentry_isInvalid (u1)) return -1;
4192 if (uentry_isInvalid (u2)) return 1;
4194 INTCOMPARERETURN (u1->ukind, u2->ukind);
4195 COMPARERETURN (ctype_compare (u1->utype, u2->utype));
4196 COMPARERETURN (bool_compare (uentry_isPriv (u1), uentry_isPriv (u2)));
4197 COMPARERETURN (sRef_compare (u1->sref, u2->sref));
4203 /* bug detected by splint:
4204 ** uentry.c:753,14: Return value type bool does not match declared type int: TRUE
4209 return (multiVal_compare (uentry_getConstantValue (u1),
4210 uentry_getConstantValue (u2)));
4214 return (ctype_compare (u1->info->datatype->type, u2->info->datatype->type));
4216 COMPARERETURN (typeIdSet_compare (uentry_accessType (u1),
4217 uentry_accessType (u2)));
4218 return (uentryList_compareParams (uentry_getParams (u1),
4219 uentry_getParams (u2)));
4221 return (typeIdSet_compare (uentry_accessType (u1),
4222 uentry_accessType (u2)));
4225 ** Functions are never equivalent
4228 if (u1 - u2 < 0) /* evans 2001-08-21: was: ((int) u1 < (int) u2), changed to remove gcc warning */
4238 COMPARERETURN (generic_compare (u1->info->var->kind, u2->info->var->kind));
4239 COMPARERETURN (generic_compare (sRef_getOrigAliasKind (u1->sref),
4240 sRef_getOrigAliasKind (u2->sref)));
4241 COMPARERETURN (generic_compare (sRef_getOrigExKind (u1->sref),
4242 sRef_getOrigExKind (u2->sref)));
4243 COMPARERETURN (generic_compare (u1->info->var->checked,
4244 u2->info->var->checked));
4245 COMPARERETURN (generic_compare (u1->info->var->defstate,
4246 u2->info->var->defstate));
4247 return (generic_compare (u1->info->var->nullstate,
4248 u2->info->var->nullstate));
4250 COMPARERETURN (ctype_compare (u1->info->datatype->type,
4251 u2->info->datatype->type));
4252 COMPARERETURN (ynm_compare (u1->info->datatype->mut,
4253 u2->info->datatype->mut));
4254 return (generic_compare (u1->info->datatype->abs, u2->info->datatype->abs));
4263 ** all entries are: <type>[@<info>]*#<name>
4265 ** info depends on kind:
4269 advanceField (char **s)
4271 reader_checkChar (s, '@');
4275 advanceName (char **s)
4277 reader_checkChar (s, '#');
4281 vkind_fromInt (int i)
4283 if /*@+enumint@*/ (i < VKFIRST || i > VKLAST) /*@=enumint@*/
4285 llbuglit ("vkind_fromInt: out of range");
4292 uentry_makeConstantBase (/*@only@*/ cstring name, ctype ct,
4293 typeIdSet access, nstate nullstate,
4294 /*@keep@*/ fileloc loc, /*@only@*/ multiVal m)
4296 uentry e = uentry_alloc ();
4301 e->sref = sRef_makeConst (ct);
4303 sRef_setNullState (e->sref, nullstate, loc);
4304 e->storageclass = SCNONE;
4306 if (fileloc_isSpec (loc))
4308 e->whereSpecified = loc;
4309 e->whereDeclared = fileloc_undefined;
4313 e->whereSpecified = fileloc_undefined;
4314 e->whereDeclared = loc;
4317 e->whereDefined = fileloc_undefined;
4318 e->uses = filelocList_new ();
4319 e->isPrivate = FALSE;
4320 e->hasNameError = FALSE;
4325 e->warn = warnClause_undefined;
4327 e->info = (uinfo) dmalloc (sizeof (*e->info));
4328 e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
4329 e->info->uconst->access = access;
4330 e->info->uconst->macro = FALSE; /* fix this when macro info added to library */
4331 uentry_setConstantValue (e, m);
4332 sRef_storeState (e->sref);
4337 static /*@only@*/ uentry
4338 uentry_makeVariableBase (/*@only@*/ cstring name, ctype ct, vkind kind,
4339 sstate defstate, nstate isnull, alkind aliased,
4340 exkind exp, chkind checked,
4341 /*@only@*/ fileloc loc)
4343 uentry e = uentry_alloc ();
4348 e->storageclass = SCNONE;
4350 e->sref = sRef_makeType (ct);
4351 sRef_setNullState (e->sref, isnull, loc);
4353 e->whereDefined = fileloc_undefined;
4355 if (fileloc_isSpec (loc))
4357 e->whereSpecified = loc;
4358 e->whereDeclared = fileloc_undefined;
4362 e->whereSpecified = fileloc_undefined;
4363 e->whereDeclared = loc;
4366 e->isPrivate = FALSE;
4367 e->hasNameError = FALSE;
4372 e->uses = filelocList_new ();
4373 e->warn = warnClause_undefined;
4375 e->info = (uinfo) dmalloc (sizeof (*e->info));
4376 e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
4377 e->info->var->kind = kind;
4378 e->info->var->checked = checked;
4379 e->info->var->defstate = defstate;
4381 sRef_setDefState (e->sref, defstate, loc);
4383 e->info->var->nullstate = sRef_getNullState (e->sref);
4385 sRef_setExKind (e->sref, exp, loc);
4386 sRef_setAliasKind (e->sref, aliased, loc);
4388 sRef_storeState (e->sref);
4390 /*DRL ADDED 9-1-2000 */
4391 e->info->var->bufinfo = NULL;
4396 static /*@only@*/ uentry
4397 uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, qual abstract,
4398 ynm mut, ctype rtype, alkind ak, exkind exp,
4399 sstate defstate, nstate isnull,
4400 /*@only@*/ fileloc loc)
4402 uentry e = uentry_alloc ();
4404 e->ukind = KDATATYPE;
4405 /* e->shallowCopy = FALSE; */
4408 e->storageclass = SCNONE;
4409 e->sref = sRef_makeUnknown ();
4410 DPRINTF (("Merge null 1: %s", sRef_unparseFull (e->sref)));
4413 ** This is only setting null state. (I think?)
4416 if (ctype_isUA (ct))
4418 uentry te = usymtab_getTypeEntrySafe (ctype_typeId (ct));
4420 if (uentry_isValid (te))
4422 sRef_setStateFromUentry (e->sref, te);
4426 /* problem for recursive type definitions */
4430 sRef_setAliasKind (e->sref, ak, loc);
4431 sRef_setExKind (e->sref, exp, loc);
4433 sRef_setDefState (e->sref, defstate, loc);
4435 if (qual_isEitherAbstract (abstract) && ctype_isUnknown (ct) && isnull == NS_UNKNOWN)
4437 isnull = NS_ABSNULL;
4440 DPRINTF (("Merge null: %s", sRef_unparseFull (e->sref)));
4441 sRef_mergeNullState (e->sref, isnull);
4443 e->whereDefined = fileloc_copy (loc); /*< bogus! (but necessary for lexer) >*/
4445 if (fileloc_isSpec (loc))
4447 e->whereSpecified = loc;
4448 e->whereDeclared = fileloc_undefined;
4452 e->whereSpecified = fileloc_undefined;
4453 e->whereDeclared = loc;
4456 e->isPrivate = FALSE;
4457 e->hasNameError = FALSE;
4458 e->warn = warnClause_undefined;
4461 e->uses = filelocList_new ();
4463 e->info = (uinfo) dmalloc (sizeof (*e->info));
4464 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
4465 e->info->datatype->abs = abstract;
4466 e->info->datatype->mut = mut;
4467 e->info->datatype->type = rtype;
4469 DPRINTF (("About to store: %s", sRef_unparseFull (e->sref)));
4470 sRef_storeState (e->sref);
4471 DPRINTF (("After store: %s", sRef_unparseFull (e->sref)));
4476 static void uentry_setHasGlobs (uentry ue)
4478 llassert (uentry_isFunction (ue));
4480 ue->info->fcn->hasGlobs = TRUE;
4483 static void uentry_setHasMods (uentry ue)
4485 llassert (uentry_isFunction (ue));
4487 ue->info->fcn->hasMods = TRUE;
4490 bool uentry_hasGlobs (uentry ue)
4492 if (uentry_isFunction (ue))
4494 return (ue->info->fcn->hasGlobs);
4500 bool uentry_hasStateClauseList (uentry ue)
4502 return (uentry_isFunction (ue) && stateClauseList_isDefined (ue->info->fcn->specclauses));
4505 bool uentry_hasConditions (uentry ue)
4507 return (uentry_isFunction (ue)
4508 && (functionConstraint_isDefined (ue->info->fcn->preconditions)
4509 || functionConstraint_isDefined (ue->info->fcn->postconditions)));
4512 stateClauseList uentry_getStateClauseList (uentry ue)
4514 if (!uentry_isFunction (ue))
4516 llassert (uentry_isFunction (ue));
4517 return stateClauseList_undefined;
4520 DPRINTF (("Get state clause list: %s", uentry_unparse (ue)));
4521 return ue->info->fcn->specclauses;
4524 bool uentry_hasMods (uentry ue)
4526 if (uentry_isFunction (ue))
4528 return (ue->info->fcn->hasMods);
4535 uentry_makeFunctionBase (/*@only@*/ cstring name, ctype ct,
4537 bool hasGlobs, /*@only@*/ globSet globs,
4538 bool hasMods, /*@only@*/ sRefSet mods,
4539 alkind ak, exkind exp,
4540 sstate defstate, nstate isnull,
4544 /*@only@*/ stateClauseList specclauses,
4545 /*@only@*/ warnClause warnclause,
4546 /*@only@*/ fileloc loc)
4548 uentry e = uentry_alloc ();
4551 /* e->shallowCopy = FALSE; */
4555 e->storageclass = SCNONE;
4557 if (ctype_isFunction (ct))
4559 ret = ctype_getReturnType (ct);
4563 if (ctype_isKnown (ct))
4565 llbug (message ("not function: %s", ctype_unparse (ct)));
4568 ret = ctype_unknown;
4571 e->sref = sRef_makeType (ret);
4573 if (ctype_isUA (ret))
4575 sRef_setStateFromType (e->sref, ret);
4578 sRef_setDefined (e->sref, loc);
4579 sRef_setNullState (e->sref, isnull, loc);
4581 sRef_setAliasKind (e->sref, ak, loc);
4582 sRef_setExKind (e->sref, exp, loc);
4583 sRef_setDefState (e->sref, defstate, loc);
4585 e->whereSpecified = loc;
4586 e->whereDefined = fileloc_undefined;
4588 e->isPrivate = FALSE;
4589 e->hasNameError = FALSE;
4593 e->uses = filelocList_new ();
4594 e->warn = warnclause;
4596 e->info = (uinfo) dmalloc (sizeof (*e->info));
4597 e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn));
4599 e->info->fcn->exitCode = exitCode;
4600 e->info->fcn->specialCode = sCode;
4601 e->info->fcn->nullPred = nullPred;
4602 e->info->fcn->access = access;
4604 e->info->fcn->specclauses = specclauses;
4605 e->info->fcn->hasGlobs = hasGlobs;
4606 e->info->fcn->globs = globs;
4608 e->info->fcn->hasMods = hasMods;
4609 e->info->fcn->mods = mods;
4611 e->info->fcn->defparams = uentryList_undefined;
4612 e->whereDeclared = fileloc_undefined;
4614 sRef_storeState (e->sref);
4617 e->info->fcn->preconditions = NULL;
4621 e->info->fcn->postconditions = NULL;
4627 static /*@only@*/ uentry
4628 uentry_makeTagBase (/*@only@*/ cstring name, ekind tagkind,
4629 ctype ct, ctype rtype, /*@only@*/ fileloc loc)
4631 uentry e = uentry_alloc ();
4633 if (tagkind != KSTRUCTTAG && tagkind != KUNIONTAG && tagkind != KENUMTAG)
4635 llbuglit ("uentry_makeTagBase: not a tag type");
4638 /* e->shallowCopy = FALSE; */
4642 e->sref = sRef_makeUnknown ();
4643 e->storageclass = SCNONE;
4645 if (fileloc_isSpec (loc))
4647 e->whereSpecified = loc;
4648 e->whereDeclared = fileloc_undefined;
4652 e->whereDeclared = loc;
4653 e->whereSpecified = fileloc_undefined;
4656 e->whereDefined = fileloc_undefined;
4658 e->isPrivate = FALSE;
4659 e->hasNameError = FALSE;
4663 e->uses = filelocList_new ();
4664 e->warn = warnClause_undefined;
4666 e->info = (uinfo) dmalloc (sizeof (*e->info));
4667 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
4668 e->info->datatype->abs = qual_createUnknown ();
4669 e->info->datatype->mut = MAYBE;
4670 e->info->datatype->type = rtype;
4672 sRef_storeState (e->sref);
4678 uentry_makeIterBase (/*@only@*/ cstring name, typeIdSet access,
4679 ctype ct, /*@only@*/ fileloc loc)
4681 uentry e = uentry_alloc ();
4683 /* e->shallowCopy = FALSE; */
4687 e->sref = sRef_makeUnknown ();
4688 e->storageclass = SCNONE;
4690 if (fileloc_isSpec (loc))
4692 e->whereSpecified = loc;
4693 e->whereDeclared = fileloc_undefined;
4697 e->whereDeclared = loc;
4698 e->whereSpecified = fileloc_undefined;
4701 e->whereDefined = fileloc_undefined;
4703 e->isPrivate = FALSE;
4704 e->hasNameError = FALSE;
4708 e->uses = filelocList_new ();
4709 e->warn = warnClause_undefined;
4711 e->info = (uinfo) dmalloc (sizeof (*e->info));
4712 e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
4713 e->info->iter->access = access;
4714 e->info->iter->mods = sRefSet_undefined;
4715 e->info->iter->globs = globSet_undefined;
4717 sRef_storeState (e->sref);
4722 uentry_makeEndIterBase (/*@only@*/ cstring name, typeIdSet access,
4723 /*@only@*/ fileloc loc)
4725 uentry e = uentry_alloc ();
4727 /* e->shallowCopy = FALSE; */
4728 e->ukind = KENDITER;
4729 e->storageclass = SCNONE;
4731 e->utype = ctype_unknown;
4732 e->sref = sRef_makeUnknown ();
4734 if (fileloc_isSpec (loc))
4736 e->whereSpecified = loc;
4737 e->whereDeclared = fileloc_undefined;
4741 e->whereDeclared = loc;
4742 e->whereSpecified = fileloc_undefined;
4745 e->whereDefined = fileloc_undefined;
4747 e->isPrivate = FALSE;
4748 e->hasNameError = FALSE;
4752 e->uses = filelocList_new ();
4753 e->warn = warnClause_undefined;
4755 e->info = (uinfo) dmalloc (sizeof (*e->info));
4756 e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
4757 e->info->enditer->access = access;
4758 sRef_storeState (e->sref);
4763 void uentry_markFree (/*@unused@*/ /*@owned@*/ uentry u)
4771 uentry_undump (ekind kind, fileloc loc, char **s)
4775 DPRINTF (("Uentry undump: %s", *s));
4779 reader_checkChar (s, '!');
4780 reader_checkChar (s, '.');
4781 ue = uentry_makeElipsisMarker ();
4785 ctype ct = ctype_undump (s);
4799 reader_checkChar (s, '|');
4801 if (reader_optCheckChar (s, '@'))
4803 tkind = vkind_fromInt (reader_getInt (s));
4804 reader_checkChar (s, '|');
4811 if (reader_optCheckChar (s, '$'))
4813 defstate = SS_UNKNOWN;
4814 isnull = NS_UNKNOWN;
4815 aliased = AK_IMPTEMP;
4817 checked = CH_UNKNOWN;
4819 else if (reader_optCheckChar (s, '&'))
4821 defstate = SS_DEFINED;
4822 isnull = NS_UNKNOWN;
4823 aliased = AK_IMPTEMP;
4825 checked = CH_UNKNOWN;
4827 else if (reader_optCheckChar (s, '^'))
4829 defstate = SS_UNKNOWN;
4830 isnull = NS_UNKNOWN;
4831 aliased = AK_IMPTEMP;
4833 checked = CH_UNKNOWN;
4837 defstate = sstate_fromInt (reader_getInt (s));
4838 advanceField (s); isnull = nstate_fromInt (reader_getInt (s));
4839 advanceField (s); aliased = alkind_fromInt (reader_getInt (s));
4841 if (reader_optCheckChar (s, '&'))
4844 checked = CH_UNKNOWN;
4848 advanceField (s); exp = exkind_fromInt (reader_getInt (s));
4849 advanceField (s); checked = (chkind) (reader_getInt (s));
4854 name = reader_getStringWord (s);
4856 llassert (!cstring_equal (name, GLOBAL_MARKER_NAME));
4858 ue = uentry_makeVariableBase (name, ct, tkind, defstate,
4859 isnull, aliased, exp,
4860 checked, fileloc_copy (loc));
4873 advanceField (s); abstract = qual_abstractFromCodeChar (reader_loadChar (s));
4874 advanceField (s); mut = ynm_fromCodeChar (reader_loadChar (s));
4875 advanceField (s); defstate = sstate_fromInt (reader_getInt (s));
4876 advanceField (s); isnull = nstate_fromInt (reader_getInt (s));
4877 advanceField (s); aliased = alkind_fromInt (reader_getInt (s));
4878 advanceField (s); exp = exkind_fromInt (reader_getInt (s));
4879 advanceField (s); rtype = ctype_undump (s);
4881 name = reader_getStringWord (s);
4882 DPRINTF (("Datatype %s, Exp = %s", name, exkind_unparse (exp)));
4883 ue = uentry_makeDatatypeBase (name, ct, abstract, mut, rtype,
4884 aliased, exp, defstate, isnull,
4885 fileloc_copy (loc));
4902 stateClauseList specclauses = stateClauseList_undefined;
4903 warnClause warnclause = warnClause_undefined;
4905 if (reader_optCheckChar (s, '$'))
4907 defstate = SS_DEFINED;
4908 isnull = NS_UNKNOWN;
4909 exitCode = XK_UNKNOWN;
4911 nullPred = qual_createUnknown ();
4915 advanceField (s); defstate = sstate_fromInt (reader_getInt (s));
4916 advanceField (s); isnull = nstate_fromInt (reader_getInt (s));
4917 advanceField (s); exitCode = exitkind_fromInt (reader_getInt (s));
4918 advanceField (s); specc = specCode_fromInt (reader_getInt (s));
4919 advanceField (s); nullPred = qual_undump (s);
4922 if (reader_optCheckChar (s, '$'))
4925 globs = globSet_undefined;
4927 mods = sRefSet_undefined;
4929 else if (reader_optCheckChar (s, '^'))
4932 globs = globSet_undefined;
4934 mods = sRefSet_undefined;
4938 advanceField (s); hasGlobs = bool_fromInt (reader_getInt (s));
4939 advanceField (s); globs = globSet_undump (s);
4940 advanceField (s); hasMods = bool_fromInt (reader_getInt (s));
4941 advanceField (s); mods = sRefSet_undump (s);
4944 if (reader_optCheckChar (s, '$'))
4951 advanceField (s); ak = alkind_fromInt (reader_getInt (s));
4952 advanceField (s); exp = exkind_fromInt (reader_getInt (s));
4955 advanceField (s); access = typeIdSet_undump (s);
4958 ** Optional clauses: Start with @<code>:
4961 while (reader_optCheckChar (s, '@'))
4963 if (reader_optCheckChar (s, 'W')) /* Warn clause */
4965 reader_checkChar (s, ':');
4966 warnclause = warnClause_undump (s);
4968 else if (reader_optCheckChar (s, 'S')) /* stateClause List */
4970 reader_checkChar (s, ':');
4971 specclauses = stateClauseList_undump (s);
4979 advanceName (s); name = reader_getStringWord (s);
4981 ue = uentry_makeFunctionBase (name, ct, access,
4984 ak, exp, defstate, isnull,
4985 exitCode, specc, nullPred,
4988 fileloc_copy (loc));
4989 DPRINTF (("Undump: %s", uentry_unparse (ue)));
4996 advanceField (s); access = typeIdSet_undump (s);
4997 advanceName (s); name = reader_getStringWord (s);
4999 ue = uentry_makeIterBase (name, access, ct,
5000 fileloc_copy (loc));
5007 advanceField (s); access = typeIdSet_undump (s);
5008 advanceName (s); name = reader_getStringWord (s);
5010 ue = uentry_makeEndIterBase (name, access, fileloc_copy (loc));
5020 if (reader_optCheckChar (s, '$'))
5022 val = multiVal_undefined;
5023 access = typeIdSet_undefined;
5024 nullstate = NS_UNKNOWN;
5028 advanceField (s); val = multiVal_undump (s);
5029 advanceField (s); access = typeIdSet_undump (s);
5030 advanceField (s); nullstate = nstate_fromInt (reader_getInt (s));
5033 advanceName (s); name = reader_getStringWord (s);
5035 ue = uentry_makeConstantBase (name, ct, access,
5036 nullstate, fileloc_copy (loc), val);
5045 advanceField (s); rtype = ctype_undump (s);
5046 advanceName (s); name = reader_getStringWord (s);
5047 ue = uentry_makeTagBase (name, kind, ct, rtype, fileloc_copy (loc));
5051 llcontbuglit ("uentry_undump: invalid");
5052 ue = uentry_undefined;
5055 llcontbuglit ("uentry_undump: elips marker");
5056 ue = uentry_undefined;
5065 uentry_dump (uentry v)
5067 return (uentry_dumpAux (v, FALSE));
5071 uentry_dumpParam (uentry v)
5073 llassertprint (uentry_isVariable (v) || uentry_isElipsisMarker (v),
5074 ("dump: %s", uentry_unparseFull (v)));
5076 return (uentry_dumpAux (v, TRUE));
5080 uentry_dumpAux (uentry v, bool isParam)
5082 llassert (uentry_isValid (v));
5083 llassert (!uentry_isGlobalMarker (v));
5085 DPRINTF (("Dump uentry: [%p]", v));
5086 DPRINTF (("Dumping entry: %s", uentry_unparseFull (v)));
5091 llcontbuglit ("uentry_dump: invalid entry");
5092 return cstring_undefined;
5094 return (message ("!."));
5098 vkind vk = v->info->var->kind;
5099 sstate dss = sRef_getDefState (v->sref);
5100 nstate nst = sRef_getNullState (v->sref);
5101 alkind alk = sRef_getAliasKind (v->sref);
5102 exkind exk = sRef_getExKind (v->sref);
5103 chkind chk = v->info->var->checked;
5105 DPRINTF (("Dumping var"));
5107 if (dss == SS_UNKNOWN
5108 && nst == NS_UNKNOWN
5109 && alk == AK_IMPTEMP
5110 && exk == XO_UNKNOWN
5111 && chk == CH_UNKNOWN)
5113 sdump = cstring_makeLiteral ("$");
5115 else if (dss == SS_DEFINED
5116 && nst == NS_UNKNOWN
5117 && alk == AK_IMPTEMP
5118 && exk == XO_UNKNOWN
5119 && chk == CH_UNKNOWN)
5121 sdump = cstring_makeLiteral ("&");
5123 else if (dss == SS_UNKNOWN
5124 && nst == NS_UNKNOWN
5125 && alk == AK_UNKNOWN
5126 && exk == XO_UNKNOWN
5127 && chk == CH_UNKNOWN)
5129 sdump = cstring_makeLiteral ("^");
5131 else if (exk == XO_UNKNOWN
5132 && chk == CH_UNKNOWN)
5134 sdump = message ("%d@%d@%d&",
5141 sdump = message ("%d@%d@%d@%d@%d",
5152 return (message ("%q|@%d|%q#%s",
5153 ctype_dump (v->utype),
5156 isParam ? cstring_undefined : v->uname));
5160 return (message ("%q|%q#%s",
5161 ctype_dump (v->utype),
5163 isParam ? cstring_undefined : v->uname));
5169 DPRINTF (("Dumping datatype: %s -> %s type: %s [%d]",
5171 exkind_unparse (sRef_getExKind (v->sref)),
5172 ctype_unparse (v->utype), (int) v->utype));
5175 return (message ("%q@%c@%s@%d@%d@%d@%d@%q#%s",
5176 ctype_dump (v->utype),
5177 qual_abstractCode (v->info->datatype->abs),
5178 ynm_unparseCode (v->info->datatype->mut),
5179 (int) sRef_getDefState (v->sref),
5180 (int) sRef_getNullState (v->sref),
5181 (int) sRef_getAliasKind (v->sref),
5182 (int) sRef_getExKind (v->sref),
5183 ctype_dump (v->info->datatype->type),
5187 cstring sdump, gdump, adump, xdump;
5188 alkind alk = sRef_getAliasKind (v->sref);
5189 exkind exk = sRef_getExKind (v->sref);
5191 if (sRef_getDefState (v->sref) == SS_DEFINED
5192 && !nstate_isKnown (sRef_getNullState (v->sref))
5193 && !exitkind_isKnown (v->info->fcn->exitCode)
5194 && v->info->fcn->specialCode == SPC_NONE
5195 && qual_isUnknown (v->info->fcn->nullPred))
5197 sdump = cstring_makeLiteral ("$");
5201 sdump = message ("@%d@%d@%d@%d@%x",
5202 (int) sRef_getDefState (v->sref),
5203 (int) sRef_getNullState (v->sref),
5204 (int) v->info->fcn->exitCode,
5205 (int) v->info->fcn->specialCode,
5206 qual_dump (v->info->fcn->nullPred));
5209 if (!uentry_hasGlobs(v) && !uentry_hasMods (v))
5211 gdump = cstring_makeLiteral ("$");
5213 else if (uentry_hasGlobs (v) && globSet_isEmpty (uentry_getGlobs (v))
5214 && uentry_hasMods (v) && sRefSet_isEmpty (uentry_getMods (v)))
5216 gdump = cstring_makeLiteral ("^");
5220 gdump = message ("@%s@%q@%s@%q",
5221 bool_dump (uentry_hasGlobs (v)),
5222 globSet_dump (uentry_getGlobs (v)),
5223 bool_dump (uentry_hasMods (v)),
5224 sRefSet_dump (uentry_getMods (v)));
5227 if (alk == AK_UNKNOWN && exk == XO_UNKNOWN)
5229 adump = cstring_makeLiteral ("$");
5233 adump = message ("@%d@%d", (int) alk, (int) exk);
5236 xdump = cstring_undefined;
5238 if (uentry_hasWarning (v))
5240 xdump = message ("%q@W:%q", xdump, warnClause_dump (v->warn));
5243 if (uentry_hasStateClauseList (v))
5245 xdump = message ("%q@S:%q", xdump, stateClauseList_dump (v->info->fcn->specclauses));
5248 return (message ("%q%q%q%q@%q%q#%s",
5249 ctype_dump (v->utype),
5253 typeIdSet_dump (uentry_accessType (v)),
5258 return (message ("%q@%q#%s",
5259 ctype_dump (v->utype),
5260 typeIdSet_dump (v->info->iter->access),
5263 return (message ("%q@%q#%s",
5264 ctype_dump (v->utype),
5265 typeIdSet_dump (uentry_accessType (v)),
5272 if (multiVal_isUnknown (uentry_getConstantValue (v))
5273 && typeIdSet_isEmpty (uentry_accessType (v))
5274 && (sRef_getNullState (v->sref) == NS_UNKNOWN))
5276 sdump = cstring_makeLiteral ("$");
5280 sdump = message ("@%q@%q@%d",
5281 multiVal_dump (uentry_getConstantValue (v)),
5282 typeIdSet_dump (uentry_accessType (v)),
5283 (int) sRef_getNullState (v->sref));
5286 return (message ("%q%q#%s",
5287 ctype_dump (v->utype),
5294 return (message ("%q@%q#%s",
5295 ctype_dump (v->utype),
5296 ctype_dump (v->info->datatype->type), v->uname));
5303 uentry_unparseAbbrev (uentry v)
5305 if (!uentry_isVariable (v))
5307 llcontbuglit ("uentry_unparseAbbrev: not variable");
5308 return uentry_unparse (v);
5311 return (message ("%s %q", ctype_unparseDeep (v->utype), uentry_getName (v)));
5315 uentry_unparse (uentry v)
5319 if (uentry_isUndefined (v)) return (cstring_makeLiteral ("<undefined>"));
5320 if (uentry_isElipsisMarker (v)) return (cstring_makeLiteral ("..."));
5322 st = uentry_getName (v);
5324 if (cstring_isDefined (st))
5326 return (ctype_unparseDeclaration (v->utype, st));
5331 return (cstring_copy (ctype_unparse (v->utype)));
5336 uentry_unparseFull (uentry v)
5338 if (uentry_isUndefined (v))
5340 return (cstring_makeLiteral ("<undefined>"));
5346 res = message ("[%p] %s %s: %s [spec: %q; decl: %q; def: %q]",
5347 v, ekind_unparse (v->ukind), v->uname,
5348 ctype_unparse (v->utype),
5349 fileloc_unparse (uentry_whereSpecified (v)),
5350 fileloc_unparse (uentry_whereDeclared (v)),
5351 fileloc_unparse (uentry_whereDefined (v)));
5353 DPRINTF (("uentry: %s", res));
5355 if (uentry_isDatatype (v))
5357 res = message ("%q / type: %s mut: %s abs: %s state: %q",
5360 (ctype_isDefined (v->info->datatype->type)
5361 ? v->info->datatype->type : ctype_unknown),
5362 ynm_unparse (v->info->datatype->mut),
5363 qual_unparse (v->info->datatype->abs),
5364 sRef_unparseState (v->sref));
5366 else if (uentry_isFunction (v))
5368 res = message ("%q / sref: %q / mods: %q / "
5369 "globs: %q / clauses: %q / pre: %q / post: %q",
5371 sRef_unparseFull (v->sref),
5372 sRefSet_unparse (v->info->fcn->mods),
5373 globSet_unparse (v->info->fcn->globs),
5374 stateClauseList_unparse (v->info->fcn->specclauses),
5375 functionConstraint_unparse (v->info->fcn->preconditions),
5376 functionConstraint_unparse (v->info->fcn->postconditions));
5378 else if (uentry_isIter (v))
5380 res = message ("%q / sref: %q",
5382 sRef_unparseFull (v->sref));
5384 else if (uentry_isVariable (v))
5386 res = message ("%q / sref: %q / kind <%d> isout <%d> null <%d> used <%d>",
5388 sRef_unparseFull (v->sref),
5389 (int) v->info->var->kind,
5390 (int) v->info->var->defstate,
5391 (int) v->info->var->nullstate,
5393 DPRINTF (("sref: [%p]", v->sref));
5394 DPRINTF (("sref: %s", sRef_unparseDebug (v->sref)));
5395 /* DPRINTF (("sref: %s", sRef_unparseDeep (v->sref))); */
5397 else if (uentry_isConstant (v))
5399 res = message ("%q = %q / %q",
5400 res, multiVal_unparse (uentry_getConstantValue (v)),
5401 sRef_unparseFull (v->sref));
5405 res = message ("%q :: %q", res, uentry_unparse (v));
5412 bool uentry_hasAccessType (uentry e)
5414 if (uentry_isValid (e))
5419 return (!typeIdSet_isEmpty (e->info->iter->access));
5421 return (!typeIdSet_isEmpty (e->info->enditer->access));
5423 return (!typeIdSet_isEmpty (e->info->fcn->access));
5426 return (!typeIdSet_isEmpty (e->info->uconst->access));
5435 typeIdSet uentry_accessType (uentry e)
5437 if (uentry_isValid (e))
5442 return (e->info->iter->access);
5444 return (e->info->enditer->access);
5446 return (e->info->fcn->access);
5449 return (e->info->uconst->access);
5455 return typeIdSet_undefined;
5459 uentry_isVariable (uentry e)
5461 return (uentry_isVar (e));
5465 uentry_isSpecified (uentry e)
5467 return (uentry_isValid (e) && !fileloc_isUndefined (e->whereSpecified));
5471 uentry_isReallySpecified (uentry e)
5473 return (uentry_isValid (e)
5474 && fileloc_isRealSpec (e->whereSpecified));
5478 uentry_isVar (uentry e)
5480 return (!uentry_isUndefined (e) && e->ukind == KVAR);
5484 uentry_isFakeTag (uentry e)
5486 return (uentry_isValid (e) && strchr (cstring_toCharsSafe (e->uname), '!') != 0);
5490 uentry_isDatatype (uentry e)
5492 return (!uentry_isUndefined (e) &&
5493 (e->ukind == KDATATYPE || e->ukind == KSTRUCTTAG ||
5494 e->ukind == KUNIONTAG || e->ukind == KENUMTAG));
5498 uentry_setAbstract (uentry e)
5502 llassert (uentry_isDatatype (e)
5503 && (qual_isUnknown (e->info->datatype->abs)));
5505 oldid = ctype_typeId (e->info->datatype->type);
5506 e->info->datatype->abs = qual_createAbstract ();
5507 e->info->datatype->type = ctype_createAbstract (oldid);
5511 uentry_setConcrete (uentry e)
5513 llassert (uentry_isDatatype (e)
5514 && (qual_isUnknown (e->info->datatype->abs)
5515 || qual_isConcrete (e->info->datatype->abs)));
5517 e->info->datatype->abs = qual_createConcrete ();
5521 uentry_isAbstractDatatype (uentry e)
5523 return (uentry_isDatatype (e)
5524 && (qual_isEitherAbstract (e->info->datatype->abs)));
5528 uentry_isMaybeAbstract (uentry e)
5530 return (uentry_isDatatype (e)
5531 && (!qual_isConcrete (e->info->datatype->abs)));
5535 uentry_isMutableDatatype (uentry e)
5537 if (uentry_isDatatype (e))
5539 if (ctype_isNumAbstract (e->info->datatype->type))
5545 return ynm_toBoolRelaxed (e->info->datatype->mut);
5553 uentry_isRefCountedDatatype (uentry e)
5555 return (uentry_isDatatype (e) && (sRef_isRefCounted (uentry_getSref (e))));
5559 uentry_isParam (uentry u)
5561 return (uentry_isVariable (u) && (u->info->var->kind == VKPARAM
5562 || u->info->var->kind == VKYIELDPARAM));
5566 uentry_isExpandedMacro (uentry u)
5568 return (uentry_isVariable (u) && (u->info->var->kind == VKEXPMACRO));
5572 uentry_isSefParam (uentry u)
5574 return (uentry_isVariable (u)
5575 && (u->info->var->kind == VKSEFPARAM
5576 || u->info->var->kind == VKREFSEFPARAM
5577 || u->info->var->kind == VKSEFRETPARAM
5578 || u->info->var->kind == VKREFSEFRETPARAM));
5582 uentry_isRefParam (uentry u)
5584 return (uentry_isVariable (u)
5585 && (u->info->var->kind == VKREFPARAM
5586 || u->info->var->kind == VKREFYIELDPARAM
5587 || u->info->var->kind == VKREFSEFPARAM
5588 || u->info->var->kind == VKREFSEFRETPARAM));
5592 uentry_isAnyParam (uentry u)
5594 return (uentry_isVariable (u)
5595 && ((u->info->var->kind == VKPARAM)
5596 || (u->info->var->kind == VKSEFPARAM)
5597 || (u->info->var->kind == VKYIELDPARAM)
5598 || (u->info->var->kind == VKRETPARAM)
5599 || (u->info->var->kind == VKSEFRETPARAM)));
5603 uentry_getDefState (uentry u)
5605 if (uentry_isValid (u))
5607 return (sRef_getDefState (u->sref));
5611 return (SS_UNKNOWN);
5616 uentry_isOut (uentry u)
5618 return ((uentry_isVariable (u) && (u->info->var->defstate == SS_ALLOCATED))
5619 || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
5623 uentry_isPartial (uentry u)
5625 return ((uentry_isVariable (u) && (u->info->var->defstate == SS_PARTIAL))
5626 || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
5630 uentry_isStateSpecial (uentry u)
5632 return ((uentry_isVariable (u)
5633 && (u->info->var->defstate == SS_SPECIAL))
5634 || (uentry_isValid (u) && sRef_isStateSpecial (u->sref)));
5637 exitkind uentry_getExitCode (uentry ue)
5639 if (uentry_isFunction (ue))
5641 return ue->info->fcn->exitCode;
5649 qual uentry_nullPred (uentry u)
5651 llassert (uentry_isRealFunction (u));
5653 if (uentry_isFunction (u))
5655 return (u->info->fcn->nullPred);
5659 return qual_createUnknown ();
5664 ** Note for variables, this is checking the declared state, not the current state.
5668 uentry_possiblyNull (uentry u)
5670 return ((uentry_isVariable (u) && (nstate_possiblyNull (u->info->var->nullstate)))
5671 || (uentry_isDatatype (u) && (sRef_possiblyNull (u->sref))));
5675 uentry_getAliasKind (uentry u)
5677 if (uentry_isValid (u))
5679 return (sRef_getAliasKind (uentry_getSref (u)));
5688 uentry_getExpKind (uentry u)
5690 if (uentry_isValid (u))
5692 return (sRef_getExKind (uentry_getSref (u)));
5701 uentry_isIter (uentry e)
5703 return (!uentry_isUndefined (e) && e->ukind == KITER);
5707 uentry_isEndIter (uentry e)
5709 return (!uentry_isUndefined (e) && e->ukind == KENDITER);
5713 uentry_isRealFunction (uentry e)
5715 return (uentry_isFunction (e) ||
5716 (uentry_isVariable (e) && ctype_isFunction (uentry_getType (e))));
5720 uentry_hasName (uentry e)
5722 if (uentry_isValid (e))
5724 cstring s = e->uname;
5726 return (!(cstring_isEmpty (s) || cstring_equalLit (s, "...")
5727 || uentry_isFakeTag (e)));
5736 ** Returns true for fake tags.
5737 ** This is used for dumping the library
5740 bool uentry_hasRealName (uentry e)
5742 return (uentry_isValid (e)
5743 && cstring_isNonEmpty (e->uname)
5744 && !uentry_isGlobalMarker (e));
5748 /*@observer@*/ globSet
5749 uentry_getGlobs (uentry l)
5751 if (uentry_isInvalid (l))
5753 return globSet_undefined;
5756 if (uentry_isFunction (l))
5758 return l->info->fcn->globs;
5760 else if (uentry_isIter (l))
5762 return l->info->iter->globs;
5764 else if (uentry_isEndIter (l))
5766 return globSet_undefined;
5770 if (l->ukind == KVAR)
5772 llcontbug (message ("Bad call to uentry_getGlobs (var): %q (%s)",
5774 ekind_unparse (l->ukind)));
5778 llcontbug (message ("Bad call to uentry_getGlobs: %q (%s)",
5780 ekind_unparse (l->ukind)));
5783 return globSet_undefined;
5788 /* Make Microsoft VC++ happy */
5789 # pragma warning (disable : 4715)
5792 /*@observer@*/ sRefSet
5793 uentry_getMods (uentry l)
5795 llassert (uentry_isValid (l));
5797 if (l->ukind != KFCN && l->ukind != KITER && l->ukind != KENDITER)
5799 llcontbug (message ("Bad call to uentry_getMods: %q", uentry_unparse (l)));
5800 return sRefSet_undefined;
5803 if (uentry_isFunction (l))
5805 return l->info->fcn->mods;
5807 else if (uentry_isIter (l))
5809 return l->info->iter->mods;
5811 else if (uentry_isEndIter (l))
5813 return sRefSet_undefined;
5822 uentry_getKind (uentry e)
5824 llassert (uentry_isValid (e));
5828 /*@observer@*/ multiVal uentry_getConstantValue (uentry e)
5830 llassert (uentry_isEitherConstant (e));
5831 return (sRef_getValue (e->sref));
5834 /*@observer@*/ uentryList
5835 uentry_getParams (uentry l)
5837 if (uentry_isInvalid (l)) return uentryList_undefined;
5844 ctype ct = l->utype;
5846 if (ctype_isFunction (ct))
5848 return (ctype_argsFunction (ct));
5852 return uentryList_undefined;
5857 ctype ct = l->utype;
5859 /*drl 12/10/2002 changed to fix bug involving multiple redefines of library functions in macros. Bug was reported by Malcolm Parsons
5861 Old code was simplly llassert (ctype_isFunction (ct) );
5864 llassert (ctype_isFunction (ct) || context_inMacro() );
5866 return (ctype_argsFunction (ct));
5873 /*@observer@*/ cstring
5874 uentry_rawName (uentry e)
5876 if (uentry_isValid (e))
5882 return cstring_undefined;
5887 uentry_getOptName (uentry e)
5889 cstring s = uentry_getName (e);
5891 if (cstring_isDefined (s))
5893 s = cstring_appendChar (s, ' ');
5900 uentry_getName (uentry e)
5902 cstring ret = cstring_undefined;
5904 if (uentry_isValid (e))
5906 if (uentry_isAnyTag (e))
5908 ret = fixTagName (e->uname);
5910 else if (uentry_isAnyParam (e))
5912 ret = cstring_copy (fixParamName (e->uname));
5916 ret = cstring_copy (e->uname);
5923 cstring uentry_observeRealName (uentry e)
5925 cstring ret = cstring_undefined;
5927 if (uentry_isValid (e))
5929 if (uentry_isAnyTag (e))
5931 if (isFakeTag (e->uname))
5933 ret = cstring_undefined;
5937 ret = plainTagName (e->uname);
5940 else if (uentry_isAnyParam (e))
5942 ret = fixParamName (e->uname);
5953 cstring uentry_getRealName (uentry e)
5955 if (uentry_isValid (e))
5957 if (uentry_isAnyTag (e))
5959 return (cstring_undefined);
5966 return cstring_undefined;
5969 ctype uentry_getType (uentry e)
5971 if (uentry_isValid (e))
5977 return ctype_unknown;
5981 fileloc uentry_whereLast (uentry e)
5985 if (uentry_isInvalid (e))
5987 return fileloc_undefined;
5990 loc = e->whereDefined;
5992 if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
5997 loc = uentry_whereDeclared (e);
5999 if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
6004 loc = uentry_whereSpecified (e);
6008 fileloc uentry_whereEither (uentry e)
6010 if (uentry_isInvalid (e)) return fileloc_undefined;
6012 if (fileloc_isDefined (e->whereDefined)
6013 && !fileloc_isExternal (e->whereDefined))
6015 return e->whereDefined;
6017 else if (fileloc_isDefined (e->whereDeclared))
6019 return e->whereDeclared;
6023 return e->whereSpecified;
6027 fileloc uentry_whereSpecified (uentry e)
6029 if (uentry_isInvalid (e)) return fileloc_undefined;
6031 return (e->whereSpecified);
6034 fileloc uentry_whereDefined (uentry e)
6036 if (uentry_isInvalid (e)) return fileloc_undefined;
6038 return (e->whereDefined);
6041 fileloc uentry_whereDeclared (uentry e)
6043 if (uentry_isInvalid (e)) return fileloc_undefined;
6045 return (e->whereDeclared);
6048 /*@observer@*/ fileloc
6049 uentry_whereEarliest (uentry e)
6051 if (uentry_isInvalid (e)) return fileloc_undefined;
6053 if (fileloc_isDefined (e->whereSpecified))
6055 return (e->whereSpecified);
6057 else if (fileloc_isDefined (e->whereDeclared))
6059 return (e->whereDeclared);
6063 return e->whereDefined;
6068 uentry_setFunctionDefined (uentry e, fileloc loc)
6070 if (uentry_isValid (e))
6072 llassert (uentry_isFunction (e));
6074 if (fileloc_isUndefined (e->whereDeclared))
6076 e->whereDeclared = fileloc_update (e->whereDeclared, loc);
6079 if (!fileloc_isDefined (e->whereDefined))
6081 e->whereDefined = fileloc_update (e->whereDefined, loc);
6087 uentry_setDeclDef (uentry e, fileloc f)
6089 uentry_setDeclared (e, f);
6091 if (!uentry_isFunction (e)
6092 && !(uentry_isVariable (e) && uentry_isExtern (e)))
6094 uentry_setDefined (e, f);
6099 uentry_setDeclaredForce (uentry e, fileloc f)
6101 llassert (uentry_isValid (e));
6102 e->whereDeclared = fileloc_update (e->whereDeclared, f);
6106 uentry_setDeclaredForceOnly (uentry e, fileloc f)
6108 llassert (uentry_isValid (e));
6109 fileloc_free (e->whereDeclared);
6110 e->whereDeclared = f;
6114 uentry_setDeclaredOnly (uentry e, /*@only@*/ fileloc f)
6118 llassert (uentry_isValid (e));
6119 oldloc = e->whereDeclared;
6121 if (fileloc_isDefined (oldloc))
6123 if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
6125 e->whereDeclared = f;
6126 fileloc_free (oldloc);
6135 e->whereDeclared = f;
6136 fileloc_free (oldloc);
6141 uentry_setDeclared (uentry e, fileloc f)
6145 llassert (uentry_isValid (e));
6146 oldloc = e->whereDeclared;
6148 if (fileloc_isDefined (oldloc))
6150 if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
6152 e->whereDeclared = fileloc_update (e->whereDeclared, f);
6161 e->whereDeclared = fileloc_update (e->whereDeclared, f);
6166 uentry_clearDefined (uentry e)
6168 if (uentry_isValid (e))
6170 e->whereDefined = fileloc_update (e->whereDefined, fileloc_undefined);
6175 uentry_setDefined (uentry e, fileloc f)
6179 llassert (uentry_isValid (e));
6180 oldloc = e->whereDefined;
6182 if (fileloc_isDefined (oldloc))
6184 if (fileloc_isLib (oldloc)
6185 || fileloc_isImport (oldloc)
6186 || fileloc_isBuiltin (oldloc)
6187 || fileloc_isPreproc (oldloc))
6189 e->whereDefined = fileloc_update (e->whereDefined, f);
6193 if (fileloc_equal (oldloc, f) || context_processingMacros ())
6199 if (optgenerror (FLG_REDEF,
6200 message ("%s %q redefined",
6201 ekind_capName (e->ukind),
6202 uentry_getName (e)),
6205 llgenindentmsg (message ("Previous definition of %q",
6206 uentry_getName (e)),
6214 e->whereDefined = fileloc_update (e->whereDefined, f);
6219 uentry_isCodeDefined (uentry e)
6221 llassert (uentry_isValid (e));
6223 return (fileloc_isDefined (e->whereDefined));
6227 uentry_isDeclared (uentry e)
6229 if (uentry_isValid (e))
6231 return (fileloc_isDefined (e->whereDeclared));
6237 sRef uentry_getSref (uentry e)
6239 /* not true, used for functions too (but shouldn't be? */
6240 /* llassertprint (e->ukind == KVAR, ("uentry_getSref: not variable!")); */
6242 if (uentry_isInvalid (e)) return sRef_undefined;
6247 sRef uentry_getOrigSref (uentry e)
6249 /* evans 2003-04-12 - removed for now */
6250 /* evans 2001-09-09 - need to fix this
6251 if (uentry_isValid (e))
6253 if (uentry_isVariable (e))
6255 return e->info->var->origsref;
6259 sRef sr = sRef_copy (uentry_getSref (e));
6261 sRef_resetState (sr);
6262 sRef_clearDerived (sr);
6268 return sRef_undefined;
6272 if (uentry_isValid (e))
6274 sRef sr = sRef_copy (uentry_getSref (e));
6276 sRef_resetState (sr);
6277 sRef_clearDerived (sr);
6279 if (uentry_isVariable (e))
6281 sRef_setDefState (sr, e->info->var->defstate, fileloc_undefined);
6282 sRef_setNullState (sr, e->info->var->nullstate, fileloc_undefined);
6289 return sRef_undefined;
6294 ** requires: uentry e is not in a hashed symbol table
6298 uentry_setName (uentry e, /*@only@*/ cstring n)
6300 llassert (uentry_isValid (e));
6302 cstring_free (e->uname);
6307 uentry_setType (uentry e, ctype t)
6309 if (uentry_isValid (e))
6312 sRef_setType (e->sref, t);
6317 uentry_resetParams (uentry ue, /*@only@*/ uentryList pn)
6320 ctype rettype = ctype_unknown;
6322 llassert (uentry_isValid (ue));
6324 uentry_convertVarFunction (ue);
6325 llassert (uentry_isFunction (ue));
6327 rct = ctype_realType (ue->utype);
6329 if (ctype_isFunction (rct))
6331 rettype = ctype_getReturnType (rct);
6334 ue->utype = ctype_makeNFParamsFunction (rettype, pn);
6338 uentry_setRefParam (uentry e)
6340 if (!uentry_isVar (e))
6342 llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
6346 if (e->info->var->kind == VKSEFPARAM)
6348 e->info->var->kind = VKREFSEFPARAM;
6350 else if (e->info->var->kind == VKSEFRETPARAM)
6352 e->info->var->kind = VKREFSEFRETPARAM;
6354 else if (e->info->var->kind == VKYIELDPARAM)
6356 e->info->var->kind = VKREFYIELDPARAM;
6360 e->info->var->kind = VKREFPARAM;
6366 uentry_setParam (uentry e)
6368 if (!uentry_isVar (e))
6370 if (uentry_isElipsisMarker (e))
6376 llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
6383 if (e->info->var->kind == VKYIELDPARAM
6384 || e->info->var->kind == VKSEFPARAM
6385 || e->info->var->kind == VKSEFRETPARAM)
6391 e->info->var->kind = VKPARAM;
6395 e->uname = makeParam (e->uname);
6396 cstring_free (oldname);
6401 uentry_setSref (uentry e, sRef s)
6403 if (uentry_isValid (e))
6405 if (sRef_isValid (e->sref))
6407 sRef_mergeStateQuietReverse (e->sref, s);
6411 e->sref = sRef_saveCopy (s);
6417 uentry_getAbstractType (uentry e)
6419 llassert (uentry_isDatatype (e));
6422 ** This assertion removed.
6423 ** Okay to have undefined type, for system types
6425 llassertprintret (!ctype_isUndefined (e->info->datatype->type),
6426 ("uentry_getAbstractType %q: undefined", uentry_unparseFull (e)),
6431 if (ctype_isUndefined (e->info->datatype->type))
6433 return ctype_unknown;
6437 ** Sadly, a kludge...
6440 if (ctype_isUserBool (e->info->datatype->type)) {
6444 return e->info->datatype->type;
6447 ctype uentry_getRealType (uentry e)
6450 typeId uid = typeId_invalid;
6452 if (uentry_isInvalid (e))
6454 return ctype_unknown;
6457 if (!uentry_isDatatype (e))
6459 /* This shouldn't happen, except when types are redeclared in strange ways */
6460 return ctype_unknown;
6463 if (uentry_isAnyTag (e))
6468 if (uentry_isAbstractType (e))
6470 ct = uentry_getAbstractType (e);
6472 if (ctype_isManifestBool (ct)) {
6476 llassert (ctype_isUA (ct));
6478 uid = ctype_typeId (ct);
6480 if (!context_hasAccess (uid))
6486 ct = uentry_getType (e);
6488 /* if (ctype_isUserBool (ct)) return ct; */
6490 if (ctype_isManifestBool (ct)) {
6494 if (ctype_isUA (ct))
6496 typeId iid = ctype_typeId (ct);
6498 if (typeId_equal (iid, uid))
6500 llcontbug (message ("uentry_getRealType: recursive type! %s",
6501 ctype_unparse (ct)));
6506 /* evs 2000-07-25: possible infinite recursion ? */
6507 uentry ue2 = usymtab_getTypeEntry (iid);
6511 llcontbug (message ("Bad recursion: %q", uentry_unparseFull (e)));
6512 return ctype_unknown;
6515 return uentry_getRealType (ue2);
6524 ctype uentry_getForceRealType (uentry e)
6527 typeId uid = typeId_invalid;
6529 if (uentry_isInvalid (e))
6531 return ctype_unknown;
6534 llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e)));
6536 if (uentry_isAnyTag (e))
6541 if (uentry_isAbstractType (e))
6543 ct = uentry_getAbstractType (e);
6544 llassert (ctype_isUA (ct));
6546 uid = ctype_typeId (ct);
6547 /* no check for access! */
6550 ct = uentry_getType (e);
6552 /* evs 2000-07-25 */
6553 /* if (ctype_isUserBool (ct)) return ct; */
6555 if (ctype_isManifestBool (ct)) {
6559 if (ctype_isUA (ct))
6561 typeId iid = ctype_typeId (ct);
6563 if (typeId_equal (iid, uid))
6565 llcontbug (message ("uentry_getRealType: recursive type! %s",
6566 ctype_unparse (ct)));
6571 return uentry_getForceRealType (usymtab_getTypeEntry (iid));
6580 uentry uentry_nameCopy (cstring name, uentry e)
6582 uentry enew = uentry_alloc ();
6584 llassert (uentry_isValid (e));
6586 /* enew->shallowCopy = FALSE; */
6587 enew->ukind = e->ukind;
6589 enew->utype = e->utype;
6590 enew->whereSpecified = fileloc_copy (e->whereSpecified);
6591 enew->whereDefined = fileloc_copy (e->whereDefined);
6592 enew->whereDeclared = fileloc_copy (e->whereDeclared);
6593 enew->sref = sRef_copy (e->sref);
6594 enew->used = e->used;
6596 enew->isPrivate = e->isPrivate;
6597 enew->hasNameError = FALSE;
6599 enew->uses = filelocList_new ();
6600 enew->warn = warnClause_undefined;
6602 enew->storageclass = e->storageclass;
6603 enew->info = uinfo_copy (e->info, e->ukind);
6609 uentry_setDatatype (uentry e, typeId uid)
6611 llassert (uentry_isDatatype (e));
6613 if (uentry_isAbstractType (e))
6615 if (qual_isNumAbstract (e->info->datatype->abs))
6617 e->info->datatype->type = ctype_createNumAbstract (uid);
6621 llassert (qual_isAbstract (e->info->datatype->abs));
6622 e->info->datatype->type = ctype_createAbstract (uid);
6627 e->info->datatype->type = ctype_createUser (uid);
6632 uentry_setSpecDef (/*@special@*/ uentry e, /*@keep@*/ fileloc f)
6633 /*@defines e->whereSpecified, e->whereDeclared, e->whereDefined@*/
6636 llassert (uentry_isValid (e));
6638 if (fileloc_isSpec (f) || fileloc_isImport (f))
6640 e->whereSpecified = f;
6641 e->whereDeclared = fileloc_undefined;
6642 e->whereDefined = fileloc_undefined;
6646 e->whereSpecified = fileloc_undefined;
6647 e->whereDeclared = f;
6648 e->whereDefined = fileloc_undefined;
6651 llassert (fileloc_storable (f));
6655 ucinfo_free (/*@only@*/ ucinfo u)
6661 uvinfo_free (/*@only@*/ uvinfo u)
6663 /*drl7x added 6/29/01 */
6664 free (u->bufinfo); /* evans - 2001-07-19 fixed this bug */
6669 udinfo_free (/*@only@*/ udinfo u)
6675 ufinfo_free (/*@only@*/ ufinfo u)
6677 globSet_free (u->globs);
6678 sRefSet_free (u->mods);
6679 stateClauseList_free (u->specclauses);
6684 uiinfo_free (/*@only@*/ uiinfo u)
6690 ueinfo_free (/*@only@*/ ueinfo u)
6695 static /*@only@*/ ucinfo
6696 ucinfo_copy (ucinfo u)
6698 ucinfo ret = (ucinfo) dmalloc (sizeof (*ret));
6699 ret->access = u->access;
6700 ret->macro = u->macro;
6704 static /*@only@*/ uvinfo
6705 uvinfo_copy (uvinfo u)
6707 uvinfo ret = (uvinfo) dmalloc (sizeof (*ret));
6709 ret->kind = u->kind;
6710 ret->nullstate = u->nullstate;
6711 ret->defstate = u->defstate;
6712 ret->checked = u->checked;
6715 /* drl added 07-02-001 */
6716 /* copy null terminated information */
6718 if (u->bufinfo != NULL)
6720 ret->bufinfo = (bbufinfo) dmalloc (sizeof( * u->bufinfo ) );
6721 ret->bufinfo->bufstate = u->bufinfo->bufstate;
6722 ret->bufinfo->size = u->bufinfo->size;
6723 ret->bufinfo->len = u->bufinfo->len;
6728 ret->bufinfo = NULL;
6734 static /*@only@*/ udinfo
6735 udinfo_copy (udinfo u)
6737 udinfo ret = (udinfo) dmalloc (sizeof (*ret));
6741 ret->type = u->type;
6746 static /*@only@*/ ufinfo
6747 ufinfo_copy (ufinfo u)
6749 ufinfo ret = (ufinfo) dmalloc (sizeof (*ret));
6751 ret->hasGlobs = u->hasGlobs;
6752 ret->hasMods = u->hasMods;
6753 ret->exitCode = u->exitCode;
6754 ret->specialCode = u->specialCode;
6755 ret->nullPred = u->nullPred;
6756 ret->access = u->access;
6757 ret->globs = globSet_newCopy (u->globs);
6758 ret->mods = sRefSet_newCopy (u->mods);
6759 ret->defparams = u->defparams;
6760 ret->specclauses = stateClauseList_copy (u->specclauses);
6762 ret->preconditions = functionConstraint_copy (u->preconditions);
6763 ret->postconditions = functionConstraint_copy (u->postconditions);
6768 static /*@only@*/ uiinfo
6769 uiinfo_copy (uiinfo u)
6771 uiinfo ret = (uiinfo) dmalloc (sizeof (*ret));
6773 ret->access = u->access;
6774 ret->globs = globSet_newCopy (u->globs);
6775 ret->mods = sRefSet_newCopy (u->mods);
6780 static /*@only@*/ ueinfo
6781 ueinfo_copy (ueinfo u)
6783 ueinfo ret = (ueinfo) dmalloc (sizeof (*ret));
6785 ret->access = u->access;
6790 uinfo_free (uinfo u, ekind kind)
6795 case KCONST: ucinfo_free (u->uconst); break;
6796 case KVAR: uvinfo_free (u->var); break;
6800 case KDATATYPE: udinfo_free (u->datatype); break;
6801 case KFCN: ufinfo_free (u->fcn); break;
6802 case KITER: uiinfo_free (u->iter); break;
6803 case KENDITER: ueinfo_free (u->enditer); break;
6804 case KELIPSMARKER: break;
6805 case KINVALID: break;
6811 static /*@only@*/ /*@null@*/ uinfo
6812 uinfo_copy (uinfo u, ekind kind)
6814 if (kind == KELIPSMARKER || kind == KINVALID)
6820 uinfo ret = (uinfo) dmalloc (sizeof (*ret));
6825 case KCONST: ret->uconst = ucinfo_copy (u->uconst); break;
6826 case KVAR: ret->var = uvinfo_copy (u->var); break;
6830 case KDATATYPE: ret->datatype = udinfo_copy (u->datatype); break;
6831 case KFCN: ret->fcn = ufinfo_copy (u->fcn); break;
6832 case KITER: ret->iter = uiinfo_copy (u->iter); break;
6833 case KENDITER: ret->enditer = ueinfo_copy (u->enditer); break;
6841 uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry e)
6843 filelocList_free (e->uses);
6844 cstring_free (e->uname);
6846 uinfo_free (e->info, e->ukind);
6848 fileloc_free (e->whereSpecified);
6849 fileloc_free (e->whereDefined);
6850 fileloc_free (e->whereDeclared);
6852 warnClause_free (e->warn);
6858 extern void uentry_markOwned (/*@owned@*/ uentry u)
6860 sfreeEventually (u);
6864 uentry_free (/*@only@*/ uentry e)
6866 if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
6868 uentry_reallyFree (e);
6873 ** For uentry's in the global or file scope
6877 uentry_freeComplete (/*@only@*/ uentry e)
6879 if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
6881 DPRINTF (("Free complete: %s", sRef_unparseFull (e->sref)));
6882 /*@i@*/ sRef_free (e->sref);
6883 e->sref = sRef_undefined;
6884 uentry_reallyFree (e);
6889 ** requires old->kind != new->kind, old->uname = new->uname
6893 KindConformanceError (/*@unique@*/ uentry old, uentry unew, bool mustConform)
6895 llassert (uentry_isValid (old));
6896 llassert (uentry_isValid (unew));
6898 if ((uentry_isEitherConstant (unew) || uentry_isDatatype (unew))
6899 && (fileloc_isPreproc (uentry_whereDeclared (old))
6900 || ctype_isUnknown (old->utype))
6901 && !uentry_isSpecified (old))
6909 if (!uentry_isDeclared (old))
6911 if (uentry_isSpecified (old))
6913 if (uentry_isSpecified (unew))
6915 llbuglit ("Respecification!");
6917 else if (uentry_isDeclared (unew))
6921 message ("%s %q inconsistently declared as %s: %t",
6922 ekind_capName (old->ukind),
6923 uentry_getName (unew),
6924 ekind_unparseLong (unew->ukind),
6926 uentry_whereLast (unew))) /* evans 2001-12-30: was uentry_whereDeclared */
6928 uentry_showWhereLastKind (old);
6940 message ("%s %q inconsistently declared as %s: %t",
6941 ekind_capName (old->ukind),
6942 uentry_getName (unew),
6943 ekind_unparseLong (unew->ukind),
6945 uentry_whereLast (unew))) /* evans 2001-12-30: was uentry_whereDeclared */
6947 uentry_showWhereLastKind (old);
6953 llassert (uentry_isDeclared (unew));
6955 DPRINTF (("Old: \n\t%s", uentry_unparseFull (old)));
6956 DPRINTF (("New: \n\t%s", uentry_unparseFull (unew)));
6960 message ("%s %q inconsistently redeclared as %s",
6961 ekind_capName (old->ukind),
6962 uentry_getName (unew),
6963 ekind_unparseLong (unew->ukind)),
6964 uentry_whereLast (unew))) /* evans 2001-12-30: was uentry_whereDeclared */
6966 uentry_showWhereLastKind (old);
6972 uentry_updateInto (old, unew);
6976 ** def is the definition of spec, modifies spec
6978 ** reports any inconsistencies
6979 ** returns the summary of all available information
6980 ** if spec and def are inconsistent, def is returned
6984 uentry_showWhereLast (uentry spec)
6986 if (uentry_isValid (spec))
6988 if (fileloc_isDefined (spec->whereDefined)
6989 && !fileloc_isLib (spec->whereDefined)
6990 /*!! && !fileloc_isPreproc (spec->whereDefined) */ )
6992 llgenindentmsg (message ("Previous definition of %q: %t",
6993 uentry_getName (spec),
6994 uentry_getType (spec)),
6995 uentry_whereDefined (spec));
6997 else if (uentry_isDeclared (spec))
6999 llgenindentmsg (message ("Previous declaration of %q: %t",
7000 uentry_getName (spec),
7001 uentry_getType (spec)),
7002 uentry_whereDeclared (spec));
7004 else if (uentry_isSpecified (spec))
7006 if (uentry_hasName (spec))
7008 llgenindentmsg (message ("Specification of %q: %t",
7009 uentry_getName (spec),
7010 uentry_getType (spec)),
7011 uentry_whereSpecified (spec));
7015 llgenindentmsg (message ("Specification: %t", uentry_getType (spec)),
7016 uentry_whereSpecified (spec));
7021 /* nothing to show */
7027 uentry_showWhereLastKind (uentry spec)
7029 if (uentry_isValid (spec))
7031 if (fileloc_isDefined (spec->whereDefined)
7032 && !fileloc_isLib (spec->whereDefined)
7033 /*!! && !fileloc_isPreproc (spec->whereDefined) */ )
7035 llgenindentmsg (message ("Previous definition of %q as %s: %t",
7036 uentry_getName (spec),
7037 ekind_unparseLong (spec->ukind),
7038 uentry_getType (spec)),
7039 uentry_whereDefined (spec));
7041 else if (uentry_isDeclared (spec))
7043 llgenindentmsg (message ("Previous declaration of %q as %s: %t",
7044 uentry_getName (spec),
7045 ekind_unparseLong (spec->ukind),
7046 uentry_getType (spec)),
7047 uentry_whereDeclared (spec));
7049 else if (uentry_isSpecified (spec))
7051 if (uentry_hasName (spec))
7053 llgenindentmsg (message ("Specification of %q as %s: %t",
7054 uentry_getName (spec),
7055 ekind_unparseLong (spec->ukind),
7056 uentry_getType (spec)),
7057 uentry_whereSpecified (spec));
7061 llgenindentmsg (message ("Specification as %s: %t",
7062 ekind_unparseLong (spec->ukind),
7063 uentry_getType (spec)),
7064 uentry_whereSpecified (spec));
7069 /* nothing to show */
7075 uentry_showDefSpecInfo (uentry ce, fileloc fwhere)
7077 fileloc loc = uentry_whereDefined (ce);
7079 if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
7081 llgenindentmsg (message ("Definition of %q", uentry_getName (ce)),
7085 loc = uentry_whereSpecified (ce);
7087 if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
7089 llgenindentmsg (message ("Specification of %q", uentry_getName (ce)),
7094 void uentry_showWhereLastExtra (uentry spec, cstring extra)
7096 if (uentry_isDeclared (spec))
7098 llgenindentmsg (message ("Previous declaration of %q: %q",
7099 uentry_getName (spec), extra),
7100 uentry_whereDeclared (spec));
7102 else if (uentry_isSpecified (spec))
7104 llgenindentmsg (message ("Specification of %q: %q",
7105 uentry_getName (spec), extra),
7106 uentry_whereSpecified (spec));
7110 cstring_free (extra);
7115 uentry_showWhereDeclared (uentry spec)
7117 if (uentry_isDeclared (spec))
7119 if (uentry_hasName (spec))
7121 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
7122 uentry_whereDeclared (spec));
7126 llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
7129 else if (uentry_isSpecified (spec))
7131 if (uentry_hasName (spec))
7133 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
7134 uentry_whereSpecified (spec));
7138 llgenindentmsg (cstring_makeLiteral ("Specification"), uentry_whereSpecified (spec));
7143 /* nothing to show */
7149 uentry_showWhereAny (uentry spec)
7151 if (uentry_isDeclared (spec))
7153 if (uentry_hasName (spec))
7155 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
7156 uentry_whereDeclared (spec));
7160 llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
7163 else if (uentry_isSpecified (spec))
7165 if (uentry_hasName (spec))
7167 llgenindentmsg (message ("Specification of %q",
7168 uentry_getName (spec)),
7169 uentry_whereSpecified (spec));
7173 llgenindentmsg (cstring_makeLiteral ("Specification"),
7174 uentry_whereSpecified (spec));
7177 else if (fileloc_isDefined (uentry_whereDefined (spec)))
7179 if (uentry_hasName (spec))
7181 llgenindentmsg (message ("Definition of %q", uentry_getName (spec)),
7182 uentry_whereDefined (spec));
7186 llgenindentmsg (cstring_makeLiteral ("Definition"), uentry_whereDefined (spec));
7191 /* nothing to show */
7196 uentry_showWhereDefined (uentry spec)
7198 if (uentry_isCodeDefined (spec))
7200 llgenindentmsg (message ("Previous definition of %q", uentry_getName (spec)),
7201 uentry_whereDefined (spec));
7206 uentry_showWhereLastPlain (uentry spec)
7208 if (uentry_isDeclared (spec))
7210 llgenindentmsg (message ("Previous declaration of %q", uentry_getName (spec)),
7211 uentry_whereDeclared (spec));
7213 else if (uentry_isSpecified (spec))
7215 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
7216 uentry_whereSpecified (spec));
7224 uentry_showWhereLastVal (uentry spec, cstring val)
7226 if (uentry_isDeclared (spec))
7228 llgenindentmsg (message ("Previous declaration of %q: %s",
7229 uentry_getName (spec), val),
7230 uentry_whereDeclared (spec));
7232 else if (uentry_isSpecified (spec))
7234 llgenindentmsg (message ("Specification of %q: %s",
7235 uentry_getName (spec), val),
7236 uentry_whereSpecified (spec));
7244 uentry_showWhereSpecified (uentry spec)
7246 if (uentry_isSpecified (spec))
7248 if (uentry_hasName (spec))
7250 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
7251 uentry_whereSpecified (spec));
7255 llgenindentmsg (cstring_makeLiteral ("Specification"),
7256 uentry_whereSpecified (spec));
7259 else if (uentry_isDeclared (spec))
7261 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
7262 uentry_whereDeclared (spec));
7266 /* nothing to show */
7271 uentry_showWhereSpecifiedExtra (uentry spec, cstring s)
7273 if (uentry_isSpecified (spec))
7275 if (uentry_hasName (spec))
7277 llgenindentmsg (message ("Specification of %q: %q",
7278 uentry_getName (spec), s),
7279 uentry_whereSpecified (spec));
7283 llgenindentmsg (message ("Specification: %q", s),
7284 uentry_whereSpecified (spec));
7287 else if (uentry_isDeclared (spec))
7289 llgenindentmsg (message ("Declaration of %q: %q",
7290 uentry_getName (spec), s),
7291 uentry_whereDeclared (spec));
7295 llgenindentmsg (message ("Previous: %q", s),
7296 uentry_whereLast (spec));
7305 checkStructConformance (uentry old, uentry unew)
7308 uentryList fold, fnew;
7311 ** requires: types of old and new are structs or unions
7314 llassert (uentry_isValid (old));
7315 llassert (uentry_isValid (unew));
7317 oldr = ctype_realType (old->utype);
7318 fold = ctype_getFields (oldr);
7320 newr = ctype_realType (unew->utype);
7321 fnew = ctype_getFields (newr);
7323 if (!uentryList_matchFields (fold, fnew))
7325 if (fileloc_equal (uentry_whereLast (old),
7326 uentry_whereLast (unew)))
7334 message ("%q %q %rdeclared with fields { %q }, %s "
7335 "with fields { %q }",
7336 cstring_makeLiteral (ctype_isStruct (newr) ? "Structure": "Union"),
7337 uentry_getName (old),
7338 uentry_isDeclared (old),
7339 uentryList_unparseAbbrev (fnew),
7340 uentry_specOrDefName (old),
7341 uentryList_unparseAbbrev (fold)),
7342 uentry_whereDeclared (unew)))
7344 uentry_showWhereLastPlain (old);
7345 uentryList_showFieldDifference (fold, fnew);
7349 old->utype = unew->utype;
7354 checkEnumConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
7357 ** requires old and new are enums
7360 ctype rold = ctype_realType (old->utype);
7361 ctype rnew = ctype_realType (unew->utype);
7362 enumNameList eold = ctype_elist (rold);
7363 enumNameList enew = ctype_elist (rnew);
7365 if (!enumNameList_match (eold, enew))
7369 message ("Enum %q declared with members { %q } but "
7370 "%s with members { %q }",
7371 uentry_getName (old),
7372 enumNameList_unparse (enew),
7373 uentry_specOrDefName (old),
7374 enumNameList_unparse (eold)),
7375 uentry_whereDeclared (unew)))
7377 uentry_showWhereSpecified (old);
7378 old->utype = unew->utype;
7384 ** either oldCurrent or newCurrent may be undefined!
7388 paramTypeError (uentry old, uentry oldCurrent, ctype oldType,
7389 uentry unew, uentry newCurrent, ctype newType,
7392 bool hasError = FALSE;
7394 if (uentry_isValid (newCurrent) && uentry_isDeclared (newCurrent))
7396 if (uentry_hasName (newCurrent))
7398 hasError = optgenerror
7400 message ("Parameter %d, %q, of function %q has inconsistent type: "
7401 "declared %t, %s %t",
7402 paramno + 1, uentry_getName (newCurrent),
7403 uentry_getName (unew),
7404 newType, uentry_specOrDefName (old), oldType),
7405 uentry_whereDeclared (newCurrent));
7409 hasError = optgenerror
7411 message ("Parameter %d of function %q has inconsistent type: "
7412 "declared %t, %s %t",
7413 paramno + 1, uentry_getName (unew),
7414 newType, uentry_specOrDefName (old), oldType),
7415 uentry_whereDeclared (newCurrent));
7417 DPRINTF (("type: %s / %s",
7418 ctype_unparse (newType),
7419 ctype_unparse (ctype_realType (newType))));
7424 if (uentry_isDeclared (unew))
7426 hasError = optgenerror
7428 message ("Parameter %d of function %s has inconsistent type: "
7429 "declared %t, %s %t",
7430 paramno + 1, unew->uname,
7431 newType, uentry_specOrDefName (old), oldType),
7432 uentry_whereDeclared (unew));
7436 hasError = optgenerror
7438 message ("Parameter %d of function %s has inconsistent type: "
7439 "declared %t, %s %t",
7440 paramno + 1, unew->uname,
7441 newType, uentry_specOrDefName (old), oldType),
7442 uentry_whereDeclared (unew));
7448 DPRINTF (("Here: %s / %s",
7449 uentry_unparseFull (oldCurrent),
7450 uentry_unparseFull (newCurrent)));
7452 if (!uentry_isUndefined (oldCurrent))
7454 if (!uentry_isUndefined (newCurrent)
7455 && cstring_equal (uentry_rawName (newCurrent), uentry_rawName (oldCurrent)))
7457 uentry_showWhereLast (oldCurrent);
7461 uentry_showWhereLastPlain (old);
7464 uentry_setType (oldCurrent, newType);
7468 uentry_showWhereLastPlain (old);
7474 nargsError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
7478 message ("Function %s %rdeclared with %d arg%&, %s with %d",
7480 uentry_isDeclared (old),
7481 uentryList_size (uentry_getParams (unew)),
7482 uentry_specOrDefName (old),
7483 uentryList_size (uentry_getParams (old))),
7484 uentry_whereDeclared (unew)))
7486 uentry_showWhereLastPlain (old);
7491 returnValueError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
7495 message ("Function %s inconsistently %rdeclared to return %t",
7497 uentry_isDeclared (old),
7498 ctype_getReturnType (unew->utype)),
7499 uentry_whereDeclared (unew)))
7501 uentry_showWhereLastVal (old, ctype_unparse (ctype_getReturnType (old->utype)));
7505 static cstring paramStorageName (uentry ue)
7507 return (cstring_makeLiteralTemp (uentry_isParam (ue) ? "param" : "storage"));
7510 static cstring fcnErrName (uentry ue)
7512 return (cstring_makeLiteralTemp (uentry_isFunction (ue) ? "to return" : "as"));
7515 extern /*@observer@*/ cstring uentry_checkedName (uentry ue)
7517 if (uentry_isVar (ue))
7519 return (checkedName (ue->info->var->checked));
7523 return (cstring_makeLiteralTemp ("<checked invalid>"));
7527 static cstring checkedName (chkind checked)
7531 case CH_UNKNOWN: return (cstring_makeLiteralTemp ("unknown"));
7532 case CH_UNCHECKED: return (cstring_makeLiteralTemp ("unchecked"));
7533 case CH_CHECKED: return (cstring_makeLiteralTemp ("checked"));
7534 case CH_CHECKMOD: return (cstring_makeLiteralTemp ("checkmod"));
7535 case CH_CHECKEDSTRICT: return (cstring_makeLiteralTemp ("checkedstrict"));
7541 void checkNullState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, bool mustConform, bool completeConform)
7546 if (uentry_isVar (unew))
7548 llassert (uentry_isVar (old));
7550 oldState = old->info->var->nullstate;
7551 newState = unew->info->var->nullstate;
7555 oldState = sRef_getNullState (old->sref);
7556 newState = sRef_getNullState (unew->sref);
7559 if (oldState == NS_ABSNULL)
7561 if (uentry_isVar (old))
7563 old->info->var->nullstate = newState;
7566 sRef_mergeNullState (old->sref, newState);
7568 else if (newState == NS_UNKNOWN)
7570 if (completeConform && newState != oldState
7571 && uentry_isReallySpecified (old))
7575 message ("%s %q specified as %s, but declared without %s qualifier",
7576 ekind_capName (unew->ukind),
7577 uentry_getName (unew),
7578 nstate_unparse (oldState),
7579 nstate_unparse (oldState)),
7580 uentry_whereDeclared (unew)))
7582 uentry_showWhereSpecified (old);
7586 if (uentry_isVar (unew))
7588 unew->info->var->nullstate = oldState;
7591 sRef_mergeNullState (unew->sref, oldState);
7593 else if (newState == NS_POSNULL)
7595 if (oldState == NS_MNOTNULL
7596 && (ctype_isUA (unew->utype)
7597 || (uentry_isFunction (unew)
7598 && ctype_isUA (ctype_getReturnType (unew->utype)))))
7600 if (uentry_isVar (unew))
7602 unew->info->var->nullstate = oldState;
7605 sRef_mergeNullState (unew->sref, oldState);
7609 if (oldState == NS_NOTNULL || oldState == NS_MNOTNULL
7610 || oldState == NS_UNKNOWN)
7617 ("%s %q inconsistently %rdeclared %s possibly null storage, "
7619 uentry_ekindName (unew),
7620 uentry_getName (unew),
7621 uentry_isDeclared (old),
7623 uentry_specOrDefName (old),
7624 cstring_makeLiteral (oldState == NS_MNOTNULL ? "with notnull" : "without null")),
7625 uentry_whereDeclared (unew)))
7627 uentry_showWhereSpecified (old);
7632 if (uentry_isVar (old))
7634 old->info->var->nullstate = newState;
7637 sRef_mergeNullState (old->sref, newState);
7640 else if (newState == NS_MNOTNULL)
7642 if (oldState != NS_MNOTNULL)
7648 message ("%s %q inconsistently %rdeclared %s notnull storage, "
7649 "%s without notnull qualifier",
7650 uentry_ekindName (unew),
7651 uentry_getName (unew),
7652 uentry_isDeclared (old),
7654 uentry_specOrDefName (old)),
7655 uentry_whereDeclared (unew)))
7657 uentry_showWhereSpecified (old);
7661 if (uentry_isVar (old))
7663 old->info->var->nullstate = newState;
7666 sRef_mergeNullState (old->sref, newState);
7671 if (uentry_isVar (unew))
7673 unew->info->var->nullstate = oldState;
7676 sRef_mergeNullState (unew->sref, oldState);
7681 void checkDefState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7682 bool mustConform, bool completeConform)
7688 if (uentry_isVar (old) && uentry_isVar (unew))
7690 oldState = old->info->var->defstate;
7691 newState = unew->info->var->defstate;
7696 oldState = sRef_getDefState (old->sref);
7697 newState = sRef_getDefState (unew->sref);
7700 if (newState != oldState
7701 && newState != SS_UNKNOWN
7702 && newState != SS_DEFINED)
7708 message ("%s %q inconsistently %rdeclared %s %s %s, "
7710 uentry_ekindName (unew),
7711 uentry_getName (unew),
7712 uentry_isDeclared (old),
7714 sstate_unparse (newState),
7715 paramStorageName (unew),
7716 uentry_specOrDefName (old),
7718 sstate_unparse (oldState),
7719 paramStorageName (unew)),
7720 uentry_whereDeclared (unew)))
7722 uentry_showWhereSpecified (old);
7726 if (vars) old->info->var->defstate = newState;
7727 sRef_setDefState (old->sref, newState, uentry_whereDeclared (unew));
7732 && (newState != oldState) && (oldState != SS_DEFINED)
7733 && uentry_isReallySpecified (old))
7737 message ("%s %q specified as %s, but declared without %s qualifier",
7738 ekind_capName (unew->ukind),
7739 uentry_getName (unew),
7740 sstate_unparse (oldState),
7741 sstate_unparse (oldState)),
7742 uentry_whereDeclared (unew)))
7744 uentry_showWhereSpecified (old);
7748 if (vars) unew->info->var->defstate = oldState;
7749 sRef_setDefState (unew->sref, oldState, uentry_whereDeclared (unew));
7754 checkAliasState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7755 bool mustConform, bool completeConform)
7760 oldKind = sRef_getAliasKind (old->sref);
7761 newKind = sRef_getAliasKind (unew->sref);
7763 if (alkind_isImplicit (newKind)
7764 || (alkind_isRefCounted (newKind) && !uentry_isDatatype (unew)))
7766 if (completeConform && !alkind_equal (newKind, oldKind)
7767 && uentry_isReallySpecified (old))
7771 message ("%s %q specified as %s, but declared without "
7772 "explicit alias qualifier",
7773 ekind_capName (unew->ukind),
7774 uentry_getName (unew),
7775 alkind_unparse (oldKind)),
7776 uentry_whereDeclared (unew)))
7778 uentry_showWhereSpecified (old);
7783 ** This really shouldn't be necessary, but it is!
7784 ** Function params (?) use new here.
7787 sRef_setAliasKind (unew->sref, oldKind, uentry_whereDeclared (unew));
7791 if (alkind_isKnown (newKind))
7793 if (!alkind_equal (oldKind, newKind))
7795 if (alkind_isKnown (oldKind))
7800 message ("%s %q inconsistently %rdeclared %s %s storage, "
7802 uentry_ekindName (unew),
7803 uentry_getName (unew),
7804 uentry_isDeclared (old),
7806 alkind_unparse (newKind),
7807 uentry_specOrDefName (old),
7808 alkind_unparse (oldKind)),
7809 uentry_whereDeclared (unew)))
7811 uentry_showWhereSpecified (old);
7813 DPRINTF (("Old: %s", sRef_unparseFull (old->sref)));
7814 DPRINTF (("New: %s", sRef_unparseFull (unew->sref)));
7815 sRef_setAliasKind (old->sref, AK_ERROR,
7816 uentry_whereDeclared (unew));
7820 sRef_setAliasKind (old->sref, newKind,
7821 uentry_whereDeclared (unew));
7826 if (!(alkind_isImplicit (newKind)))
7829 !uentry_isFunction (unew) &&
7832 message ("%s %q inconsistently %rdeclared %s %s storage, "
7833 "implicitly %s as temp storage",
7834 uentry_ekindName (unew),
7835 uentry_getName (unew),
7836 uentry_isDeclared (old),
7838 alkind_unparse (newKind),
7839 uentry_specOrDefName (old)),
7840 uentry_whereDeclared (unew)))
7842 uentry_showWhereSpecified (old);
7846 sRef_setAliasKind (old->sref, newKind,
7847 uentry_whereDeclared (unew));
7849 else /* newKind is temp or refcounted */
7856 else /* newKind unknown */
7863 checkExpState(/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7864 bool mustConform, bool completeConform)
7869 oldKind = sRef_getExKind (old->sref);
7870 newKind = sRef_getExKind (unew->sref);
7872 if (exkind_isKnown (newKind))
7874 if (oldKind != newKind)
7876 if (exkind_isKnown (oldKind))
7881 message ("%s %q inconsistently %rdeclared %s %s, %s as %s",
7882 uentry_ekindName (unew),
7883 uentry_getName (unew),
7884 uentry_isDeclared (old),
7886 exkind_unparse (newKind),
7887 uentry_specOrDefName (old),
7888 exkind_unparse (oldKind)),
7889 uentry_whereDeclared (unew)))
7891 uentry_showWhereSpecified (old);
7894 sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
7901 message ("%s %q inconsistently %rdeclared %s %s, "
7902 "implicitly %s without exposure qualifier",
7903 uentry_ekindName (unew),
7904 uentry_getName (unew),
7905 uentry_isDeclared (old),
7907 exkind_unparse (newKind),
7908 uentry_specOrDefName (old)),
7909 uentry_whereDeclared (unew)))
7911 uentry_showWhereSpecified (old);
7914 sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
7920 if (completeConform && exkind_isKnown (oldKind)
7921 && uentry_isReallySpecified (old))
7925 message ("%s %q specified as %s, but declared without "
7926 "exposure qualifier",
7927 ekind_capName (unew->ukind),
7928 uentry_getName (unew),
7929 exkind_unparse (oldKind)),
7930 uentry_whereDeclared (unew)))
7932 uentry_showWhereSpecified (old);
7936 /* yes, this is necessary! (if its a param) */
7937 sRef_setExKind (unew->sref, oldKind, fileloc_undefined);
7942 checkMetaState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7943 bool mustConform, /*@unused@*/ bool completeConform)
7945 valueTable newvals = sRef_getValueTable (unew->sref);
7947 if (valueTable_isDefined (newvals))
7949 DPRINTF (("Check meta state: %s -> %s",
7950 uentry_unparseFull (old),
7951 uentry_unparseFull (unew)));
7953 DPRINTF (("Check meta state refs: %s -> %s",
7954 sRef_unparseFull (old->sref),
7955 sRef_unparseFull (unew->sref)));
7957 DPRINTF (("Value table: %s", valueTable_unparse (newvals)));
7960 ** Copy the new values into the old ref
7963 valueTable_elements (newvals, key, newval)
7965 metaStateInfo msinfo = context_lookupMetaStateInfo (key);
7966 stateValue oldval = sRef_getMetaStateValue (old->sref, key);
7968 llassert (metaStateInfo_isDefined (msinfo));
7970 if (stateValue_isUndefined (oldval))
7972 sRef_setMetaStateValue (old->sref, key, stateValue_getValue (newval), uentry_whereLast (unew));
7976 if (stateValue_isError (oldval))
7978 if (!stateValue_isError (newval))
7980 sRef_setMetaStateValue (old->sref, key, stateValue_getValue (newval), uentry_whereLast (unew));
7984 ; /* No change necessary. */
7989 if (stateValue_getValue (newval) != stateValue_getValue (oldval))
7991 if (fileloc_isXHFile (uentry_whereDeclared (unew)))
7997 if (!stateValue_isError (newval)
7998 && !stateValue_isImplicit (newval))
8000 if (uentry_hasName (unew)
8001 || !sRef_isParam (uentry_getSref (unew)))
8006 message ("%s %q inconsistently %rdeclared %s %q, %s as %q",
8007 uentry_ekindName (unew),
8008 uentry_getName (unew),
8009 uentry_isDeclared (old),
8011 stateValue_unparseValue (newval, msinfo),
8012 uentry_specOrDefName (old),
8013 stateValue_unparseValue (oldval, msinfo)),
8014 uentry_whereDeclared (unew)))
8016 uentry_showWhereSpecified (old);
8024 message ("%s %d inconsistently %rdeclared %s %q, %s as %q",
8025 uentry_ekindName (unew),
8026 sRef_getParam (uentry_getSref (unew)),
8027 uentry_isDeclared (old),
8029 stateValue_unparseValue (newval, msinfo),
8030 uentry_specOrDefName (old),
8031 stateValue_unparseValue (oldval, msinfo)),
8032 uentry_whereDeclared (unew)))
8034 uentry_showWhereSpecified (old);
8040 DPRINTF (("Updating!"));
8041 sRef_setMetaStateValue (old->sref, key, stateValue_getValue (newval), uentry_whereLast (unew));
8045 DPRINTF (("Values match"));
8049 } end_valueTable_elements ;
8054 uentry_checkStateConformance (/*@notnull@*/ uentry old,
8055 /*@notnull@*/ uentry unew,
8056 bool mustConform, bool completeConform)
8058 checkDefState (old, unew, mustConform, completeConform);
8059 checkNullState (old, unew, mustConform, completeConform);
8060 checkAliasState (old, unew, mustConform, completeConform);
8061 checkExpState (old, unew, mustConform, completeConform);
8062 checkMetaState (old, unew, mustConform, completeConform);
8064 sRef_storeState (old->sref);
8065 sRef_storeState (unew->sref);
8069 checkVarConformance (uentry old, uentry unew, bool mustConform, bool completeConform)
8071 if (uentry_isElipsisMarker (old) || uentry_isElipsisMarker (unew))
8076 llassert (uentry_isVar (old));
8077 llassert (uentry_isVar (unew));
8079 if (cstring_isEmpty (old->uname))
8081 cstring_free (old->uname);
8082 old->uname = cstring_copy (unew->uname);
8085 if (unew->info->var->kind == VKRETPARAM
8086 || unew->info->var->kind == VKSEFRETPARAM)
8088 if (old->info->var->kind != VKRETPARAM
8089 && old->info->var->kind != VKSEFRETPARAM)
8093 message ("Parameter %q inconsistently %rdeclared as "
8094 "returned parameter",
8095 uentry_getName (unew),
8096 uentry_isDeclared (old)),
8097 uentry_whereDeclared (unew)))
8099 uentry_showWhereSpecified (old);
8100 old->info->var->kind = unew->info->var->kind;
8106 if (unew->info->var->kind == VKSEFPARAM || unew->info->var->kind == VKSEFRETPARAM)
8108 if (old->info->var->kind != VKSEFPARAM
8109 && old->info->var->kind != VKSEFRETPARAM)
8113 message ("Parameter %qinconsistently %rdeclared as "
8115 uentry_getOptName (unew),
8116 uentry_isDeclared (old)),
8117 uentry_whereDeclared (unew)))
8119 uentry_showWhereSpecified (old);
8120 old->info->var->kind = unew->info->var->kind;
8125 if (old->info->var->kind == VKSPEC)
8127 old->info->var->kind = unew->info->var->kind;
8131 unew->info->var->kind = old->info->var->kind;
8134 if (unew->info->var->checked != CH_UNKNOWN
8135 && unew->info->var->checked != old->info->var->checked)
8137 if (old->info->var->checked == CH_UNKNOWN
8138 && !fileloc_isUser (uentry_whereLast (old)))
8146 message ("Variable %q inconsistently %rdeclared as "
8147 "%s parameter (was %s)",
8148 uentry_getName (unew),
8149 uentry_isDeclared (old),
8150 checkedName (unew->info->var->checked),
8151 checkedName (old->info->var->checked)),
8152 uentry_whereDeclared (unew)))
8154 uentry_showWhereSpecified (old);
8158 old->info->var->checked = unew->info->var->checked;
8163 && (old->info->var->checked != CH_UNKNOWN)
8164 && uentry_isReallySpecified (old))
8168 message ("%s %q specified as %s, but declared without %s qualifier",
8169 ekind_capName (unew->ukind),
8170 uentry_getName (unew),
8171 checkedName (old->info->var->checked),
8172 checkedName (old->info->var->checked)),
8173 uentry_whereDeclared (unew)))
8175 uentry_showWhereSpecified (old);
8179 unew->info->var->checked = old->info->var->checked;
8182 uentry_checkStateConformance (old, unew, mustConform, completeConform);
8185 void uentry_checkMatchParam (uentry u1, uentry u2, int paramno, exprNode e)
8187 if (uentry_isElipsisMarker (u1) || uentry_isElipsisMarker (u2))
8192 llassert (uentry_isVar (u1));
8193 llassert (uentry_isVar (u2));
8195 if (u1->info->var->kind != u2->info->var->kind) {
8196 if (u1->info->var->kind == VKSEFRETPARAM) {
8197 if (u2->info->var->kind == VKRETPARAM) {
8200 message ("Function types are inconsistent. Parameter %d is "
8201 "sef parameter, but non-sef parameter in "
8202 "assigned function: %s",
8203 paramno, exprNode_unparse (e)),
8205 } else if (u2->info->var->kind == VKSEFPARAM) {
8208 message ("Function types are inconsistent. Parameter %d is "
8209 "returns parameter, but non-returns parameter in "
8210 "assigned function: %s",
8211 paramno, exprNode_unparse (e)),
8216 message ("Function types are inconsistent. Parameter %d is "
8217 "sef returns parameter, but non-sef returns parameter in "
8218 "assigned function: %s",
8219 paramno, exprNode_unparse (e)),
8222 } else if (u1->info->var->kind == VKRETPARAM) {
8225 message ("Function types are inconsistent. Parameter %d is "
8226 "returns parameter, but non-returns parameter in "
8227 "assigned function: %s",
8228 paramno, exprNode_unparse (e)),
8230 } else if (u1->info->var->kind == VKSEFPARAM) {
8233 message ("Function types are inconsistent. Parameter %d is "
8234 "sef parameter, but non-sef parameter in "
8235 "assigned function: %s",
8236 paramno, exprNode_unparse (e)),
8239 if (u2->info->var->kind == VKSEFRETPARAM) {
8242 message ("Function types are inconsistent. Parameter %d is "
8243 "normal parameter, but sef returns parameter in "
8244 "assigned function: %s",
8245 paramno, exprNode_unparse (e)),
8247 } else if (u2->info->var->kind == VKSEFPARAM) {
8250 message ("Function types are inconsistent. Parameter %d is "
8251 "normal parameter, but sef parameter in "
8252 "assigned function: %s",
8253 paramno, exprNode_unparse (e)),
8255 } else if (u2->info->var->kind == VKRETPARAM) {
8258 message ("Function types are inconsistent. Parameter %d is "
8259 "normal parameter, but returns parameter in "
8260 "assigned function: %s",
8261 paramno, exprNode_unparse (e)),
8269 if (u1->info->var->defstate != u2->info->var->defstate)
8273 message ("Function types are inconsistent. Parameter %d is "
8274 "%s, but %s in assigned function: %s",
8276 sstate_unparse (u1->info->var->defstate),
8277 sstate_unparse (u2->info->var->defstate),
8278 exprNode_unparse (e)),
8282 if (u1->info->var->nullstate != u2->info->var->nullstate)
8286 message ("Function types are inconsistent. Parameter %d is "
8287 "%s, but %s in assigned function: %s",
8289 nstate_unparse (u1->info->var->nullstate),
8290 nstate_unparse (u2->info->var->nullstate),
8291 exprNode_unparse (e)),
8295 if (sRef_getAliasKind (u1->sref) != sRef_getAliasKind (u2->sref))
8299 message ("Function types are inconsistent. Parameter %d is "
8300 "%s, but %s in assigned function: %s",
8302 alkind_unparse (sRef_getAliasKind (u1->sref)),
8303 alkind_unparse (sRef_getAliasKind (u2->sref)),
8304 exprNode_unparse (e)),
8308 if (sRef_getExKind (u1->sref) != sRef_getExKind (u2->sref))
8312 message ("Function types are inconsistent. Parameter %d is "
8313 "%s, but %s in assigned function: %s",
8315 exkind_unparse (sRef_getExKind (u1->sref)),
8316 exkind_unparse (sRef_getExKind (u2->sref)),
8317 exprNode_unparse (e)),
8322 static void uentry_convertIntoFunction (/*@notnull@*/ uentry old)
8325 ** Convert old into a function
8329 old->utype = ctype_unknown;
8330 old->info->fcn = (ufinfo) dmalloc (sizeof (*old->info->fcn));
8331 old->info->fcn->hasMods = FALSE;
8332 old->info->fcn->hasGlobs = FALSE;
8333 old->info->fcn->exitCode = XK_UNKNOWN;
8334 old->info->fcn->nullPred = qual_createUnknown ();
8335 old->info->fcn->specialCode = SPC_NONE;
8336 old->info->fcn->access = typeIdSet_undefined;
8337 old->info->fcn->globs = globSet_undefined;
8338 old->info->fcn->defparams = uentryList_undefined;
8339 old->info->fcn->mods = sRefSet_undefined;
8340 old->info->fcn->specclauses = NULL;
8341 old->info->fcn->preconditions = NULL;
8342 old->info->fcn->postconditions = NULL;
8346 checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old,
8347 /*@notnull@*/ uentry unew,
8348 bool mustConform, /*@unused@*/ bool completeConform)
8350 uentryList oldParams = uentry_getParams (old);
8351 uentryList newParams = uentry_getParams (unew);
8352 ctype newType = unew->utype;
8353 ctype oldType = ctype_realType (old->utype);
8354 ctype oldRetType = ctype_unknown;
8355 ctype newRetType = ctype_unknown;
8357 DPRINTF (("Function conform: %s ==> %s",
8358 uentry_unparseFull (old),
8359 uentry_unparseFull (unew)));
8361 if (uentry_isForward (old))
8363 mustConform = FALSE;
8364 uentry_updateInto (old, unew);
8369 ** check return values
8372 if (ctype_isKnown (oldType))
8374 if (ctype_isFunction (oldType))
8376 oldRetType = ctype_getReturnType (oldType);
8382 message ("%s %q declared as function, but previously declared as %s",
8383 ekind_capName (unew->ukind),
8384 uentry_getName (unew),
8385 ekind_unparseLong (old->ukind)),
8386 uentry_whereDeclared (unew)))
8388 uentry_showWhereLast (old);
8391 uentry_convertIntoFunction (old);
8396 if (ctype_isKnown (newType))
8398 llassert (ctype_isFunction (newType));
8399 newRetType = ctype_getReturnType (newType);
8402 if (ctype_isKnown (oldRetType) && ctype_isKnown (newRetType)
8403 && !ctype_matchDef (newRetType, oldRetType))
8405 if (mustConform) returnValueError (old, unew);
8409 if (ctype_isConj (newRetType))
8411 if (ctype_isConj (oldRetType))
8413 if (!ctype_sameAltTypes (newRetType, oldRetType))
8417 message ("Function %q inconsistently %rdeclared to "
8418 "return alternate types %s "
8419 "(types match, but alternates are not identical, "
8420 "so checking may not be correct)",
8421 uentry_getName (unew),
8422 uentry_isDeclared (old),
8423 ctype_unparse (newRetType)),
8424 uentry_whereDeclared (unew)))
8426 uentry_showWhereLastVal (old, ctype_unparse (oldRetType));
8432 old->utype = ctype_makeFunction (oldRetType, uentryList_copy (newParams));
8437 DPRINTF (("Before state: %s",
8438 uentry_unparseFull (old)));
8439 uentry_checkStateConformance (old, unew, mustConform, completeConform);
8440 DPRINTF (("After state: %s",
8441 uentry_unparseFull (old)));
8443 if (!exitkind_equal (unew->info->fcn->exitCode, old->info->fcn->exitCode))
8445 if (exitkind_isKnown (unew->info->fcn->exitCode))
8449 message ("Function %q inconsistently %rdeclared using %s",
8450 uentry_getName (unew),
8451 uentry_isDeclared (old),
8452 exitkind_unparse (unew->info->fcn->exitCode)),
8453 uentry_whereDeclared (unew)))
8455 uentry_showWhereSpecified (old);
8460 unew->info->fcn->exitCode = old->info->fcn->exitCode;
8464 if (!qual_isUnknown (unew->info->fcn->nullPred))
8466 if (!qual_match (old->info->fcn->nullPred, unew->info->fcn->nullPred))
8470 message ("Function %q inconsistently %rdeclared using %s",
8471 uentry_getName (unew),
8472 uentry_isDeclared (old),
8473 qual_unparse (unew->info->fcn->nullPred)),
8474 uentry_whereDeclared (unew)))
8476 uentry_showWhereSpecified (old);
8482 unew->info->fcn->nullPred = old->info->fcn->nullPred;
8485 if (unew->info->fcn->specialCode != SPC_NONE)
8487 if (old->info->fcn->specialCode != unew->info->fcn->specialCode)
8491 message ("Function %q inconsistently %rdeclared using %s",
8492 uentry_getName (unew),
8493 uentry_isDeclared (old),
8494 specCode_unparse (unew->info->fcn->specialCode)),
8495 uentry_whereDeclared (unew)))
8497 uentry_showWhereSpecified (old);
8503 unew->info->fcn->specialCode = old->info->fcn->specialCode;
8510 if (!uentryList_sameObject (oldParams, newParams)
8511 && (!uentryList_isMissingParams (oldParams)))
8513 if (!uentryList_isMissingParams (newParams))
8516 int nparams = uentryList_size (oldParams);
8517 bool checknames = context_maybeSet (FLG_DECLPARAMMATCH);
8519 if (nparams != uentryList_size (newParams))
8521 nargsError (old, unew);
8524 if (uentryList_size (newParams) < nparams)
8526 nparams = uentryList_size (newParams);
8529 while (paramno < nparams)
8531 uentry oldCurrent = uentryList_getN (oldParams, paramno);
8532 uentry newCurrent = uentryList_getN (newParams, paramno);
8533 ctype oldCurrentType = uentry_getType (oldCurrent);
8534 ctype newCurrentType = uentry_getType (newCurrent);
8536 llassert (uentry_isValid (oldCurrent)
8537 && uentry_isValid (newCurrent));
8539 if (!uentry_isElipsisMarker (oldCurrent)
8540 && !uentry_isElipsisMarker (newCurrent))
8542 checkVarConformance (oldCurrent, newCurrent,
8543 mustConform, completeConform);
8548 if (uentry_hasName (oldCurrent)
8549 && uentry_hasName (newCurrent))
8551 cstring oldname = uentry_getName (oldCurrent);
8552 cstring pfx = context_getString (FLG_DECLPARAMPREFIX);
8554 cstring nname = uentry_getName (newCurrent);
8557 if (cstring_isDefined (pfx)
8558 && cstring_equalPrefix (oldname, pfx))
8560 oname = cstring_suffix (oldname, cstring_length (pfx));
8565 /*@-branchstate@*/ } /*@=branchstate@*/
8567 if (cstring_isDefined (pfx)
8568 && cstring_equalPrefix (nname, pfx))
8570 nnamefix = cstring_suffix (nname, cstring_length (pfx));
8575 /*@-branchstate@*/ } /*@=branchstate@*/
8577 if (!cstring_equal (oname, nnamefix))
8580 (FLG_DECLPARAMMATCH,
8581 message ("Definition parameter name %s does not match "
8582 "name of corresponding parameter in "
8585 uentry_whereLast (newCurrent)))
8587 uentry_showWhereLastPlain (oldCurrent);
8591 cstring_free (oldname);
8592 cstring_free (nname);
8596 if (!ctype_match (oldCurrentType, newCurrentType))
8598 paramTypeError (old, oldCurrent, oldCurrentType,
8599 unew, newCurrent, newCurrentType, paramno);
8603 if (ctype_isMissingParamsMarker (newCurrentType)
8604 || ctype_isElips (newCurrentType)
8605 || ctype_isMissingParamsMarker (oldCurrentType)
8606 || ctype_isElips (oldCurrentType))
8612 if (ctype_isConj (newCurrentType))
8614 if (ctype_isConj (oldCurrentType))
8616 if (!ctype_sameAltTypes (newCurrentType, oldCurrentType))
8620 message ("Parameter %q inconsistently %rdeclared with "
8621 "alternate types %s "
8622 "(types match, but alternates are not identical, "
8623 "so checking may not be correct)",
8624 uentry_getName (newCurrent),
8625 uentry_isDeclared (oldCurrent),
8626 ctype_unparse (newCurrentType)),
8627 uentry_whereDeclared (unew)))
8629 uentry_showWhereLastVal (oldCurrent,
8630 ctype_unparse (oldCurrentType));
8638 message ("Parameter %q inconsistently %rdeclared with "
8639 "alternate types %s",
8640 uentry_getName (newCurrent),
8641 uentry_isDeclared (oldCurrent),
8642 ctype_unparse (newCurrentType)),
8643 uentry_whereDeclared (unew)))
8645 uentry_showWhereLastVal (oldCurrent,
8646 ctype_unparse (oldCurrentType));
8653 if (ctype_isConj (oldCurrentType))
8655 uentry_setType (newCurrent, oldCurrentType);
8663 ** Forgot this! detected by splint:
8664 ** uentry.c:1257,15: Suspected infinite loop
8670 if (!uentryList_isMissingParams (newParams))
8672 if (ctype_isConj (oldRetType))
8674 old->utype = ctype_makeFunction (oldRetType,
8675 uentryList_copy (newParams));
8679 old->utype = unew->utype;
8683 checkGlobalsConformance (old, unew, mustConform, completeConform);
8684 checkModifiesConformance (old, unew, mustConform, completeConform);
8686 DPRINTF (("Before list: %s",
8687 uentry_unparseFull (old)));
8689 if (stateClauseList_isDefined (unew->info->fcn->specclauses))
8691 if (!stateClauseList_isDefined (old->info->fcn->specclauses))
8696 message ("Function %q redeclared using special clauses (can only "
8697 "be used in first declaration)",
8698 uentry_getName (unew)),
8699 uentry_whereDeclared (unew)))
8701 uentry_showWhereLast (old);
8705 /* need to add some checking @*/
8706 old->info->fcn->specclauses = unew->info->fcn->specclauses;
8710 /* should be able to append? */
8712 stateClauseList_checkEqual (old, unew);
8713 stateClauseList_free (unew->info->fcn->specclauses);
8714 unew->info->fcn->specclauses = stateClauseList_undefined;
8718 /*@=branchstate@*/ /* shouldn't need this */
8720 if (fileloc_isUndefined (old->whereDeclared))
8722 old->whereDeclared = fileloc_copy (unew->whereDeclared);
8724 else if (fileloc_isUndefined (unew->whereDeclared))
8726 unew->whereDeclared = fileloc_copy (old->whereDeclared);
8733 } /*@=compmempass@*/ /* I think this is a spurious warning */
8736 uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m)
8740 llassert (uentry_isValid (ue));
8741 llassert (uentry_isEitherConstant (ue));
8743 DPRINTF (("Constant value: %s / %s", uentry_unparse (ue), multiVal_unparse (m)));
8744 uval = uentry_getConstantValue (ue);
8746 if (multiVal_isDefined (uval))
8748 if (multiVal_isDefined (m))
8750 if (!multiVal_equiv (uval, m))
8754 message ("%s %q defined with inconsistent value: %q",
8755 ekind_capName (ue->ukind),
8756 uentry_getName (ue),
8757 multiVal_unparse (m)),
8760 uentry_showWhereLastExtra (ue, multiVal_unparse (uval));
8768 uentry_setConstantValue (ue, m);
8773 bool checkTypeConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
8776 bool typeError = FALSE;
8778 if (uentry_isStructTag (old) || uentry_isUnionTag (old))
8780 if (ctype_isSU (old->utype) && ctype_isSU (unew->utype))
8784 DPRINTF (("Check struct conformance: %s / %s",
8785 uentry_unparseFull (old),
8786 uentry_unparseFull (unew)));
8787 checkStructConformance (old, unew);
8792 if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
8794 llbug (message ("struct tags: bad types: %t / %t",
8795 old->utype, unew->utype));
8799 else if (uentry_isEnumTag (old))
8801 if (ctype_isEnum (old->utype) && ctype_isEnum (unew->utype))
8803 if (mustConform) checkEnumConformance (old, unew);
8807 if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
8809 llbug (message ("enum! bad type: %s / %s", ctype_unparse (old->utype),
8810 ctype_unparse (unew->utype)));
8814 else if (!ctype_match (old->utype, unew->utype))
8816 DPRINTF (("Type mismatch: %s / %s",
8817 ctype_unparse (old->utype),
8818 ctype_unparse (unew->utype)));
8820 if (cstring_equal (uentry_rawName (old), context_getBoolName ()))
8822 ctype realt = ctype_realType (unew->utype);
8824 if (ctype_isRealInt (realt) || ctype_isChar (realt))
8826 unew->utype = ctype_bool;
8832 typeError = optgenerror
8834 message ("%q defined as %s", uentry_getName (old),
8835 ctype_unparse (realt)),
8836 uentry_whereDeclared (unew));
8844 ctype oldr = ctype_realType (old->utype);
8845 ctype newr = ctype_realType (unew->utype);
8847 if (ctype_isStruct (oldr) && ctype_isStruct (newr))
8849 checkStructConformance (old, unew);
8851 else if (ctype_isUnion (oldr) && ctype_isUnion (newr))
8853 checkStructConformance (old, unew);
8855 else if (ctype_isEnum (oldr) && ctype_isEnum (newr))
8857 checkEnumConformance (old, unew);
8859 else if (uentry_isConstant (old)
8860 && (ctype_isAbstract (oldr) && ctype_isEnum (newr)))
8862 /* okay...for now! (should check the type is reset later... */
8866 DPRINTF (("YABA!"));
8869 message ("%s %q %rdeclared with inconsistent type: %t",
8870 ekind_capName (unew->ukind),
8871 uentry_getName (unew),
8872 uentry_isDeclared (old),
8874 uentry_whereDeclared (unew)))
8876 uentry_showWhereLast (old);
8892 uentry_checkDatatypeConformance (/*@notnull@*/ uentry old,
8893 /*@notnull@*/ uentry unew,
8894 bool mustConform, bool completeConform)
8896 if (ctype_isDefined (unew->info->datatype->type))
8899 ** bool is hard coded here, since it is built into LCL.
8900 ** For now, we're stuck with LCL's types.
8903 if (ctype_isDirectBool (old->utype) &&
8904 cstring_equalLit (unew->uname, "bool"))
8906 /* if (!context_getFlag (FLG_ABSTRACTBOOL))
8907 evs 2000-07-25: removed
8909 unew->utype = ctype_bool;
8912 if (ctype_isUnknown (old->info->datatype->type))
8914 old->info->datatype->type = unew->info->datatype->type;
8918 DPRINTF (("Old: %s / New: %s",
8919 uentry_unparseFull (old),
8920 uentry_unparseFull (unew)));
8921 DPRINTF (("Types: %s / %s",
8922 ctype_unparse (old->info->datatype->type),
8923 ctype_unparse (unew->info->datatype->type)));
8925 if (ctype_matchDef (old->info->datatype->type,
8926 unew->info->datatype->type))
8935 ("Type %q %s with inconsistent type: %t",
8936 uentry_getName (unew),
8937 uentry_reDefDecl (old, unew),
8938 unew->info->datatype->type),
8939 uentry_whereDeclared (unew)))
8941 uentry_showWhereLastExtra
8942 (old, cstring_copy (ctype_unparse (old->info->datatype->type)));
8945 old->info->datatype->type = unew->info->datatype->type;
8950 if (!qual_isUnknown (unew->info->datatype->abs))
8952 if (qual_isConcrete (old->info->datatype->abs)
8953 && qual_isEitherAbstract (unew->info->datatype->abs))
8955 if (!ctype_isDirectBool (old->utype))
8960 ("Datatype %q inconsistently %rdeclared as abstract type",
8961 uentry_getName (unew),
8962 uentry_isDeclared (old)),
8963 uentry_whereDeclared (unew)))
8965 uentry_showWhereLastPlain (old);
8969 else if (qual_isEitherAbstract (old->info->datatype->abs)
8970 && qual_isConcrete (unew->info->datatype->abs))
8972 if (!ctype_isDirectBool (old->utype))
8977 ("Datatype %q inconsistently %rdeclared as concrete type",
8978 uentry_getName (unew),
8979 uentry_isDeclared (old)),
8980 uentry_whereDeclared (unew)))
8982 uentry_showWhereLastPlain (old);
8993 if (qual_isEitherAbstract (old->info->datatype->abs))
8995 old->sref = unew->sref;
8996 unew->info->datatype->mut = old->info->datatype->mut;
8999 && uentry_isReallySpecified (old))
9004 ("Datatype %q specified as abstract, "
9005 "but abstract annotation not used in declaration",
9006 uentry_getName (unew)),
9007 uentry_whereDeclared (unew)))
9009 uentry_showWhereLastPlain (old);
9015 unew->info->datatype->abs = old->info->datatype->abs;
9017 if (ynm_isMaybe (unew->info->datatype->mut))
9019 if (completeConform && ynm_isOff (old->info->datatype->mut)
9020 && uentry_isReallySpecified (old))
9025 ("Datatype %q specified as immutable, "
9026 "but immutable annotation not used in declaration",
9027 uentry_getName (unew)),
9028 uentry_whereDeclared (unew)))
9030 uentry_showWhereLastPlain (old);
9034 unew->info->datatype->mut = old->info->datatype->mut;
9036 else if (ynm_isMaybe (old->info->datatype->mut))
9038 old->info->datatype->mut = unew->info->datatype->mut;
9042 if (qual_isEitherAbstract (old->info->datatype->abs))
9044 if (ynm_isOn (old->info->datatype->mut) && ynm_isOff (unew->info->datatype->mut))
9048 message ("Datatype %q inconsistently %rdeclared as immutable",
9049 uentry_getName (unew),
9050 uentry_isDeclared (old)),
9051 uentry_whereDeclared (unew)))
9053 uentry_showWhereLastPlain (old);
9058 if (ynm_isOff (old->info->datatype->mut)
9059 && ynm_isOn (unew->info->datatype->mut))
9063 message ("Datatype %q inconsistently %rdeclared as mutable",
9064 uentry_getName (unew),
9065 uentry_isDeclared (old)),
9066 uentry_whereDeclared (unew)))
9068 uentry_showWhereLastPlain (old);
9073 old->info->datatype->mut = unew->info->datatype->mut;
9076 uentry_checkStateConformance (old, unew, mustConform, completeConform);
9080 uentry_checkConstantConformance (/*@notnull@*/ uentry old,
9081 /*@notnull@*/ uentry unew,
9083 /*@unused@*/ bool completeConform)
9085 multiVal oldval = uentry_getConstantValue (old);
9086 multiVal newval = uentry_getConstantValue (unew);
9088 if (multiVal_isDefined (oldval))
9090 if (multiVal_isDefined (newval))
9092 if (!multiVal_equiv (oldval, newval))
9097 message ("%s %q %rdeclared with inconsistent value: %q",
9098 ekind_capName (unew->ukind),
9099 uentry_getName (unew),
9100 uentry_isDeclared (old),
9101 multiVal_unparse (newval)),
9102 uentry_whereDeclared (unew)))
9104 uentry_showWhereLastExtra (old, multiVal_unparse (oldval));
9108 uentry_setConstantValue (unew, multiVal_copy (oldval));
9117 uentry_setConstantValue (old, multiVal_copy (newval));
9122 uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old,
9123 /*@notnull@*/ uentry unew, bool mustConform,
9124 bool completeConform)
9126 bool typeError = FALSE;
9127 bool fcnConformance = FALSE;
9129 if (!ekind_equal (unew->ukind, old->ukind))
9132 ** okay, only if one is a function and the other is
9133 ** a variable of type function.
9136 if (unew->ukind == KENUMCONST
9137 && old->ukind == KCONST)
9139 old->ukind = KENUMCONST;
9143 if (unew->ukind == KFCN
9144 && old->ukind == KCONST
9145 && ctype_isUnknown (old->utype))
9148 ** When a function is defined with an unparam macro
9151 uentry_updateInto (old, unew);
9155 if (uentry_isExpandedMacro (old)
9156 && uentry_isEitherConstant (unew))
9158 uentry_updateInto (old, unew);
9162 if (uentry_isEndIter (unew))
9164 if (ctype_isUnknown (old->utype))
9166 if (!uentry_isSpecified (old)
9167 && uentry_isCodeDefined (unew))
9169 if (!fileloc_withinLines (uentry_whereDefined (old),
9170 uentry_whereDeclared (unew), 2))
9171 { /* bogus! will give errors if there is too much whitespace */
9175 ("Iterator finalized name %q does not match name in "
9176 "previous iter declaration (should be end_%q). This iter "
9177 "is declared at %q",
9178 uentry_getName (unew),
9179 uentry_getName (old),
9180 fileloc_unparse (uentry_whereDefined (old))),
9181 uentry_whereDeclared (old));
9185 uentry_updateInto (old, unew);
9190 KindConformanceError (old, unew, mustConform);
9194 if (uentry_isFunction (unew))
9196 if (uentry_isVariable (old))
9198 if (!ctype_isUnknown (old->utype))
9200 if (ctype_isFunction (old->utype))
9202 uentry_makeVarFunction (old);
9203 checkFunctionConformance (old, unew, mustConform,
9205 fcnConformance = TRUE;
9209 KindConformanceError (old, unew, mustConform);
9214 if (uentry_isExpandedMacro (old))
9216 if (fileloc_isUndefined (unew->whereDefined))
9218 unew->whereDefined = fileloc_update (unew->whereDefined,
9222 uentry_updateInto (old, unew);
9223 old->used = unew->used = TRUE;
9228 /* undeclared identifier */
9229 old->utype = unew->utype;
9230 uentry_makeVarFunction (old);
9231 checkFunctionConformance (old, unew, FALSE, FALSE);
9232 fcnConformance = TRUE;
9238 KindConformanceError (old, unew, mustConform);
9241 else if (uentry_isFunction (old) && uentry_isVariable (unew))
9243 if (!ctype_isUnknown (unew->utype))
9245 if (ctype_isFunction (unew->utype))
9247 uentry_makeVarFunction (unew);
9248 checkFunctionConformance (old, unew, mustConform, completeConform);
9249 fcnConformance = TRUE;
9253 KindConformanceError (old, unew, mustConform);
9258 KindConformanceError (old, unew, mustConform);
9263 KindConformanceError (old, unew, mustConform);
9269 ** check parameter lists for functions
9270 ** (before type errors, to get better messages
9273 if (uentry_isFunction (old))
9275 checkFunctionConformance (old, unew, mustConform, completeConform);
9276 fcnConformance = TRUE;
9280 if (!ctype_isUndefined (old->utype))
9282 typeError = checkTypeConformance (old, unew, mustConform);
9289 if (uentry_isEitherConstant (old) && uentry_isEitherConstant (unew))
9291 uentry_checkConstantConformance (old, unew, mustConform, completeConform);
9294 if (uentry_isDatatype (old) && uentry_isDatatype (unew))
9296 DPRINTF (("Check datatype: %s / %s",
9297 uentry_unparseFull (old),
9298 uentry_unparseFull (unew)));
9300 uentry_checkDatatypeConformance (old, unew, mustConform, completeConform);
9303 if (uentry_isVariable (old) && uentry_isVariable (unew))
9306 !ctype_matchDef (old->utype, unew->utype))
9311 ("Variable %q %s with inconsistent type (arrays and pointers are "
9312 "not identical in variable declarations): %t",
9313 uentry_getName (unew),
9314 uentry_reDefDecl (old, unew),
9316 uentry_whereDeclared (unew)))
9318 uentry_showWhereLast (old);
9321 ** Avoid repeated errors.
9324 if (uentry_isCodeDefined (old) && uentry_isCodeDefined (unew))
9326 old->whereDefined = fileloc_update (old->whereDefined,
9334 checkVarConformance (old, unew, mustConform, completeConform);
9339 /* old->utype = unew->utype; */
9343 if (ctype_isConj (old->utype))
9345 if (ctype_isConj (unew->utype))
9347 if (!ctype_sameAltTypes (old->utype, unew->utype))
9351 message ("%s %q inconsistently %rdeclared with "
9352 "alternate types %s "
9353 "(types match, but alternates are not identical, "
9354 "so checking may not be correct)",
9355 ekind_capName (uentry_getKind (old)),
9356 uentry_getName (unew),
9357 uentry_isDeclared (old),
9358 ctype_unparse (unew->utype)),
9359 uentry_whereDeclared (unew)))
9361 uentry_showWhereLastVal (old, ctype_unparse (old->utype));
9365 old->utype = unew->utype;
9372 if (ctype_isUnknown (old->utype))
9374 old->utype = unew->utype;
9379 if (unew->ukind == old->ukind)
9382 unew->info = uinfo_copy (old->info, old->ukind);
9385 sRef_storeState (old->sref);
9386 sRef_storeState (unew->sref);
9389 static void uentry_mergeConstraints (uentry spec, uentry def)
9391 if (uentry_isFunction (def))
9393 DPRINTF (("Here: %s / %s",
9394 uentry_unparseFull (spec),
9395 uentry_unparseFull (def)));
9396 /* evans 2001-07-21 */
9397 llassert (uentry_isFunction (spec));
9399 if (functionConstraint_isDefined (def->info->fcn->preconditions))
9401 if (fileloc_isXHFile (uentry_whereLast (def)))
9403 llassert (uentry_isFunction (spec));
9404 spec->info->fcn->preconditions = functionConstraint_conjoin (spec->info->fcn->preconditions,
9405 def->info->fcn->preconditions);
9407 else if (fileloc_equal (uentry_whereLast (spec), uentry_whereLast (def)))
9413 /* Check if the constraints are identical */
9418 ("Preconditions for %q redeclared. Dropping previous precondition: %q",
9419 uentry_getName (spec),
9420 functionConstraint_unparse (spec->info->fcn->preconditions)),
9421 uentry_whereLast (def)))
9423 uentry_showWhereSpecified (spec);
9426 functionConstraint_free (spec->info->fcn->preconditions);
9427 spec->info->fcn->preconditions = def->info->fcn->preconditions;
9430 def->info->fcn->preconditions = functionConstraint_undefined;
9433 if (functionConstraint_isDefined (def->info->fcn->postconditions))
9435 if (fileloc_isXHFile (uentry_whereLast (def)))
9437 llassert (uentry_isFunction (spec));
9438 DPRINTF (("Post: %s /++/ %s",
9439 functionConstraint_unparse (spec->info->fcn->postconditions),
9440 functionConstraint_unparse (def->info->fcn->postconditions)));
9441 spec->info->fcn->postconditions = functionConstraint_conjoin (spec->info->fcn->postconditions,
9442 def->info->fcn->postconditions);
9443 def->info->fcn->postconditions = functionConstraint_undefined;
9444 DPRINTF (("Conjoined post: %s", functionConstraint_unparse (spec->info->fcn->postconditions)));
9451 ("Postconditions for %q redeclared. Dropping previous postcondition: %q",
9452 uentry_getName (spec),
9453 functionConstraint_unparse (spec->info->fcn->postconditions)),
9454 uentry_whereLast (def)))
9456 uentry_showWhereSpecified (spec);
9459 functionConstraint_free (spec->info->fcn->postconditions);
9460 spec->info->fcn->postconditions = def->info->fcn->postconditions;
9461 def->info->fcn->postconditions = functionConstraint_undefined;
9468 ** modifies spec to reflect def, reports any inconsistencies
9472 uentry_mergeEntries (uentry spec, /*@only@*/ uentry def)
9474 llassert (uentry_isValid (spec));
9475 llassert (uentry_isValid (def));
9476 llassert (cstring_equal (spec->uname, def->uname));
9478 if (uentry_isFunction (def))
9480 if (uentry_isConstant (spec))
9482 llassert (ctype_isUnknown (spec->utype) || ctype_isFunction (spec->utype));
9483 uentry_makeConstantFunction (spec);
9487 uentry_convertVarFunction (spec);
9490 llassert (uentry_isFunction (spec));
9493 DPRINTF (("Merge entries: %s / %s", uentry_unparseFull (spec),
9494 uentry_unparseFull (def)));
9496 uentry_mergeConstraints (spec, def);
9498 uentry_checkConformance (spec, def, TRUE,
9499 context_getFlag (FLG_NEEDSPEC));
9501 DPRINTF (("Merge entries after conform: %s / %s",
9502 uentry_unparseFull (spec),
9503 uentry_unparseFull (def)));
9505 /* was: !(fileloc_isImport (uentry_whereSpecified (spec)))); */
9508 ** okay, declarations conform. Propagate extra information.
9511 uentry_setDefined (spec, uentry_whereDefined (def));
9512 uentry_setDeclared (spec, uentry_whereDeclared (def));
9514 if (uentry_isStatic (def))
9518 message ("%s %q specified, but declared as static",
9519 ekind_capName (def->ukind),
9520 uentry_getName (def)),
9521 uentry_whereDeclared (def)))
9523 uentry_showWhereSpecified (spec);
9528 spec->storageclass = def->storageclass;
9531 sRef_storeState (spec->sref);
9533 spec->used = def->used || spec->used;
9534 spec->hasNameError |= def->hasNameError;
9538 if (!spec->hasNameError)
9540 uentry_checkName (spec);
9549 ** Can't generate function redeclaration errors when the
9550 ** entries are merged, since we don't yet know if its the
9551 ** definition of the function.
9555 uentry_clearDecl (void)
9557 posRedeclared = uentry_undefined;
9558 fileloc_free (posLoc);
9559 posLoc = fileloc_undefined;
9563 uentry_checkDecl (void)
9565 if (uentry_isValid (posRedeclared) && !fileloc_isXHFile (posLoc))
9567 llassert (fileloc_isDefined (posLoc));
9569 if (uentry_isCodeDefined (posRedeclared))
9571 if (optgenerror (FLG_REDECL,
9572 message ("%s %q declared after definition",
9573 ekind_capName (posRedeclared->ukind),
9574 uentry_getName (posRedeclared)),
9577 llgenindentmsg (message ("Definition of %q",
9578 uentry_getName (posRedeclared)),
9579 posRedeclared->whereDeclared);
9584 if (optgenerror (FLG_REDECL,
9585 message ("%s %q declared more than once",
9586 ekind_capName (posRedeclared->ukind),
9587 uentry_getName (posRedeclared)),
9590 llgenindentmsg (message ("Previous declaration of %q",
9591 uentry_getName (posRedeclared)),
9592 posRedeclared->whereDeclared);
9597 fileloc_free (posLoc);
9598 posLoc = fileloc_undefined;
9599 posRedeclared = uentry_undefined;
9603 ** Redefinition of old as unew.
9604 ** modifies old to reflect unew, reports any inconsistencies
9608 uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew)
9610 fileloc olddef = uentry_whereDeclared (old);
9611 fileloc unewdef = uentry_whereDeclared (unew);
9615 DPRINTF (("uentry merge: %s / %s",
9616 uentry_unparseFull (old),
9617 uentry_unparseFull (unew)));
9620 fileloc_isUndefined (olddef)
9621 && fileloc_isDefined (uentry_whereDefined (old))
9622 && !uentry_isExpandedMacro (old);
9624 if (!context_getFlag (FLG_INCONDEFSLIB)
9625 && (fileloc_isLib (olddef) || fileloc_isImport (olddef)))
9627 mustConform = FALSE;
9634 llassert (uentry_isValid (old));
9635 llassert (uentry_isValid (unew));
9636 llassert (cstring_equal (old->uname, unew->uname));
9638 if (uentry_isFunction (unew) && !uentry_isFunction (old))
9640 if (uentry_isConstant (old))
9642 llassert (ctype_isUnknown (old->utype) || ctype_isFunction (old->utype));
9643 uentry_makeConstantFunction (old);
9647 uentry_convertVarFunction (old);
9650 if (!uentry_isFunction (old))
9654 message ("%s %q declared as function, but previously declared as %s",
9655 ekind_capName (unew->ukind),
9656 uentry_getName (unew),
9657 ekind_unparseLong (old->ukind)),
9658 uentry_whereDeclared (unew)))
9660 uentry_showWhereLast (old);
9663 uentry_convertIntoFunction (old);
9668 DPRINTF (("uentry merge: %s / %s",
9669 uentry_unparseFull (old),
9670 uentry_unparseFull (unew)));
9672 if (uentry_isExtern (unew))
9674 uentry_setUsed (old, unewdef);
9678 ** should check old one was extern!
9681 if (uentry_isStatic (old))
9683 if (!(uentry_isStatic (unew)))
9687 message ("%s %q shadows static declaration",
9688 ekind_capName (unew->ukind),
9689 uentry_getName (unew)),
9692 uentry_showWhereLast (old);
9697 uentry_setDeclDef (old, unewdef);
9700 else if (uentry_isStatic (unew))
9702 uentry_setDeclDef (old, unewdef);
9704 else if (uentry_isExtern (old))
9706 uentry_setDeclared (old, unewdef);
9710 if (!uentry_isExtern (unew)
9711 && !uentry_isForward (old)
9712 && !fileloc_equal (olddef, unewdef)
9713 && !fileloc_isUndefined (olddef)
9714 && !fileloc_isUndefined (unewdef)
9715 && !fileloc_isBuiltin (olddef)
9716 && !fileloc_isBuiltin (unewdef)
9717 && !uentry_isYield (old)
9718 && !(fileloc_isLib (olddef) || fileloc_isImport (olddef)))
9720 if (uentry_isVariable (old) || uentry_isVariable (unew))
9722 ; /* will report redeclaration error later */
9726 if (fileloc_isDefined (uentry_whereDefined (old)))
9730 message ("%s %q defined more than once",
9731 ekind_capName (unew->ukind),
9732 uentry_getName (unew)),
9733 uentry_whereLast (unew)))
9736 (message ("Previous definition of %q",
9737 uentry_getName (old)),
9738 uentry_whereLast (old));
9741 if (uentry_isDatatype (old) || uentry_isAnyTag (old))
9743 uentry_updateInto (old, unew);
9744 old->sref = sRef_saveCopy (old->sref);
9752 if (fileloc_isLib (olddef)
9753 || fileloc_isUndefined (olddef)
9754 || fileloc_isImport (olddef))
9756 if (uentry_isExtern (unew))
9758 if (uentry_isExtern (old)
9759 || (fileloc_isDefined (uentry_whereDeclared (old))
9760 && (!fileloc_equal (uentry_whereDeclared (old),
9761 uentry_whereDefined (old)))))
9765 message ("%s %q declared more than once",
9766 ekind_capName (unew->ukind),
9767 uentry_getName (unew)),
9768 unew->whereDeclared))
9771 (message ("Previous declaration of %q",
9772 uentry_getName (old)),
9773 old->whereDeclared);
9777 uentry_setExtern (old);
9781 uentry_setDeclared (old, unewdef); /* evans 2001-07-23 was setDefined */
9787 DPRINTF (("uentry merge: %s / %s",
9788 uentry_unparseFull (old),
9789 uentry_unparseFull (unew)));
9791 uentry_mergeConstraints (old, unew);
9792 DPRINTF (("uentry merge: %s / %s",
9793 uentry_unparseFull (old),
9794 uentry_unparseFull (unew)));
9796 uentry_checkConformance (old, unew, mustConform, FALSE);
9797 DPRINTF (("uentry merge: %s / %s",
9798 uentry_unparseFull (old),
9799 uentry_unparseFull (unew)));
9801 old->used = old->used || unew->used;
9802 old->uses = filelocList_append (old->uses, unew->uses);
9803 unew->uses = filelocList_undefined;
9805 sRef_storeState (old->sref);
9806 sRef_storeState (unew->sref);
9810 old->whereDefined = fileloc_update (old->whereDefined,
9814 DPRINTF (("here: %s", uentry_unparseFull (old)));
9817 ** No redeclaration errors for functions here, since we
9818 ** don't know if this is the definition of the function.
9821 if (fileloc_isUser (old->whereDeclared)
9822 && fileloc_isUser (unew->whereDeclared)
9823 && !fileloc_equal (old->whereDeclared, unew->whereDeclared)
9824 && !fileloc_isDefined (unew->whereDefined))
9826 if (uentry_isFunction (old))
9828 /*@-temptrans@*/ posRedeclared = old; /*@=temptrans@*/
9829 posLoc = fileloc_update (posLoc, unew->whereDeclared);
9833 if (optgenerror (FLG_REDECL,
9834 message ("%s %q declared more than once",
9835 ekind_capName (unew->ukind),
9836 uentry_getName (unew)),
9837 unew->whereDeclared))
9839 llgenindentmsg (message ("Previous declaration of %q",
9840 uentry_getName (old)),
9841 old->whereDeclared);
9846 if (fileloc_isUndefined (old->whereDefined))
9848 old->whereDefined = fileloc_update (old->whereDefined, unew->whereDefined);
9852 if (!context_processingMacros ()
9853 && fileloc_isUser (old->whereDefined)
9854 && fileloc_isUser (unew->whereDefined)
9855 && !fileloc_equal (old->whereDefined, unew->whereDefined))
9857 if (uentry_isVariable (unew) || uentry_isFunction (unew))
9859 if (uentry_isVariable (unew)
9860 && uentry_isExtern (unew))
9862 if (optgenerror (FLG_REDECL,
9863 message ("%s %q declared after definition",
9864 ekind_capName (unew->ukind),
9865 uentry_getName (unew)),
9866 unew->whereDeclared))
9868 llgenindentmsg (message ("Definition of %q",
9869 uentry_getName (old)),
9875 if (optgenerror (FLG_REDEF,
9876 message ("%s %q redefined",
9877 ekind_capName (unew->ukind),
9878 uentry_getName (unew)),
9879 unew->whereDefined))
9881 llgenindentmsg (message ("Previous definition of %q",
9882 uentry_getName (old)),
9890 if (uentry_isExternal (unew))
9892 old->whereDefined = fileloc_createExternal ();
9895 if (unew->hasNameError)
9897 old->hasNameError = TRUE;
9902 if (!old->hasNameError)
9904 uentry_checkName (old);
9907 DPRINTF (("After: %s", uentry_unparseFull (old)));
9908 llassert (!ctype_isUndefined (old->utype));
9912 uentry_copyState (uentry res, uentry other)
9914 llassert (uentry_isValid (res));
9915 llassert (uentry_isValid (other));
9917 res->used = other->used;
9919 res->info->var->kind = other->info->var->kind;
9920 res->info->var->defstate = other->info->var->defstate;
9921 res->info->var->nullstate = other->info->var->nullstate;
9922 res->info->var->checked = other->info->var->checked;
9924 sRef_copyState (res->sref, other->sref);
9928 uentry_sameKind (uentry u1, uentry u2)
9930 if (uentry_isValid (u1) && uentry_isValid (u2))
9932 if (uentry_isVar (u1) && uentry_isVar (u2))
9934 ctype c1 = u1->utype;
9935 ctype c2 = u2->utype;
9937 if (ctype_isUnknown (c1) || ctype_isUnknown (c2)) return FALSE;
9940 ** both functions, or both not functions
9943 return (bool_equal (ctype_isFunction (c1), ctype_isFunction (c2)));
9947 return ((u1->ukind == u2->ukind));
9954 static void uentry_updateInto (/*@unique@*/ uentry unew, uentry old)
9957 llassert (uentry_isValid (unew));
9958 llassert (uentry_isValid (old));
9960 DPRINTF (("Update into: %s / %s", uentry_unparseFull (unew), uentry_unparseFull (old)));
9961 okind = unew->ukind;
9962 unew->ukind = old->ukind;
9963 llassert (cstring_equal (unew->uname, old->uname));
9964 unew->utype = old->utype;
9966 if (fileloc_isDefined (unew->whereSpecified)
9967 && !fileloc_isDefined (old->whereSpecified))
9969 ; /* Keep the old value */
9973 fileloc_free (unew->whereSpecified);
9974 unew->whereSpecified = fileloc_copy (old->whereSpecified);
9977 if (fileloc_isDefined (unew->whereDefined)
9978 && !fileloc_isDefined (old->whereDefined))
9980 ; /* Keep the old value */
9984 fileloc_free (unew->whereDefined);
9985 unew->whereDefined = fileloc_copy (old->whereDefined);
9988 if (fileloc_isDefined (unew->whereDeclared)
9989 && !fileloc_isDefined (old->whereDeclared))
9991 ; /* Keep the old value */
9995 fileloc_free (unew->whereDeclared);
9996 unew->whereDeclared = fileloc_copy (old->whereDeclared);
9999 DPRINTF (("Update into: %s / %s", uentry_unparseFull (unew), uentry_unparseFull (old)));
10001 unew->sref = sRef_saveCopy (old->sref); /* Memory leak! */
10002 unew->used = old->used;
10003 unew->lset = FALSE;
10004 unew->isPrivate = old->isPrivate;
10005 unew->hasNameError = old->hasNameError;
10006 unew->uses = filelocList_append (unew->uses, old->uses);
10007 old->uses = filelocList_undefined;
10009 unew->storageclass = old->storageclass;
10010 uinfo_free (unew->info, okind);
10011 unew->info = uinfo_copy (old->info, old->ukind);
10015 uentry_copyAux (uentry e, bool saveCopy)
10018 if (uentry_isValid (e))
10020 uentry enew = uentry_alloc ();
10021 DPRINTF (("copy: %s", uentry_unparseFull (e)));
10022 enew->ukind = e->ukind;
10023 enew->uname = cstring_copy (e->uname);
10024 enew->utype = e->utype;
10026 enew->whereSpecified = fileloc_copy (e->whereSpecified);
10027 enew->whereDefined = fileloc_copy (e->whereDefined);
10028 enew->whereDeclared = fileloc_copy (e->whereDeclared);
10032 enew->sref = sRef_saveCopy (e->sref); /* Memory leak! */
10036 enew->sref = sRef_copy (e->sref);
10039 enew->used = e->used;
10040 enew->lset = FALSE;
10041 enew->isPrivate = e->isPrivate;
10042 enew->hasNameError = e->hasNameError;
10043 enew->uses = filelocList_undefined;
10045 enew->storageclass = e->storageclass;
10046 enew->info = uinfo_copy (e->info, e->ukind);
10047 enew->warn = warnClause_copy (e->warn);
10049 DPRINTF (("Here we are..."));
10050 DPRINTF (("original: %s", uentry_unparseFull (e)));
10051 DPRINTF (("copy: %s", uentry_unparse (enew)));
10052 DPRINTF (("copy: %s", uentry_unparseFull (enew)));
10057 return uentry_undefined;
10062 uentry_copy (uentry e)
10064 return uentry_copyAux (e, TRUE);
10068 uentry_copyNoSave (uentry e)
10070 return uentry_copyAux (e, FALSE);
10074 uentry_setState (uentry res, uentry other)
10076 llassert (uentry_isValid (res));
10077 llassert (uentry_isValid (other));
10079 llassert (res->ukind == other->ukind);
10080 llassert (res->ukind == KVAR);
10082 res->sref = sRef_saveCopy (other->sref);
10083 res->used = other->used;
10084 filelocList_free (res->uses);
10085 res->uses = other->uses;
10086 other->uses = filelocList_undefined;
10087 res->lset = other->lset;
10091 uentry_mergeUses (uentry res, uentry other)
10093 llassert (uentry_isValid (res));
10094 llassert (uentry_isValid (other));
10096 res->used = other->used || res->used;
10097 res->lset = other->lset || res->lset;
10098 res->uses = filelocList_append (res->uses, other->uses);
10099 other->uses = filelocList_undefined;
10104 ** This is a really ugly routine.
10106 ** gack...fix this one day.
10111 ** >> res is the false branch, other is the true branch (or continuation)
10113 ** >> res is the true branch, other is the false branch (or continutation)
10120 ** References not effected by res are propagated from other.
10124 branchStateError (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other,
10125 bool flip, clause cl, fileloc loc)
10129 message ("%s %q is %s %s, but %s %s.",
10130 ekind_capName (res->ukind), uentry_getName (res),
10131 sRef_stateVerb (res->sref), clause_nameFlip (cl, flip),
10132 sRef_stateAltVerb (res->sref), clause_nameFlip (cl, !flip)),
10135 DPRINTF (("Here: %s / %s", sRef_unparseFull (res->sref), sRef_unparseFull (other->sref)));
10137 if (sRef_isDead (res->sref))
10139 if (sRef_hasStateInfoLoc (res->sref)) {
10140 llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc);
10141 sRef_showStateInfo (res->sref);
10144 if (sRef_hasStateInfoLoc (other->sref)) {
10145 llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc);
10146 sRef_showStateInfo (other->sref);
10149 else if (sRef_isKept (res->sref))
10151 if (sRef_hasAliasInfoLoc (res->sref)) {
10152 llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc);
10153 sRef_showAliasInfo (res->sref);
10156 if (sRef_hasAliasInfoLoc (other->sref)) {
10157 llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc);
10158 sRef_showAliasInfo (other->sref);
10161 else /* dependent */
10163 if (sRef_hasAliasInfoLoc (res->sref)) {
10164 llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc);
10165 sRef_showAliasInfo (res->sref);
10168 if (sRef_hasAliasInfoLoc (other->sref)) {
10169 llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc);
10170 sRef_showAliasInfo (other->sref);
10174 sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
10178 static bool uentry_incompatibleMemoryStates (sRef rs, sRef os)
10180 alkind rk = sRef_getAliasKind (rs);
10181 alkind ok = sRef_getAliasKind (os);
10183 if (alkind_isError (rk) || alkind_isError (ok))
10189 return ((sRef_isDead (rs)
10190 || (alkind_isKept (rk) && !alkind_isKept (ok))
10191 || (alkind_isDependent (rk)
10192 && !alkind_isDependent (ok) && !alkind_isTemp (ok)))
10193 && (sRef_isAllocated (os) || sRef_isStateDefined (os)));
10198 branchStateAltError (/*@notnull@*/ uentry res,
10199 /*@notnull@*/ uentry other, bool flip,
10200 clause cl, fileloc loc)
10204 message ("%s %q is %s %s, but %s %s.",
10205 ekind_capName (res->ukind), uentry_getName (res),
10206 sRef_stateVerb (other->sref), clause_nameFlip (cl, flip),
10207 sRef_stateAltVerb (other->sref), clause_nameFlip (cl, !flip)),
10210 if (sRef_isDead (other->sref))
10212 if (sRef_hasStateInfoLoc (other->sref)) {
10213 llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc);
10214 sRef_showStateInfo (other->sref);
10217 if (sRef_hasStateInfoLoc (res->sref)) {
10218 llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc);
10219 sRef_showStateInfo (res->sref);
10224 if (sRef_hasAliasInfoLoc (other->sref)) {
10225 llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc);
10226 sRef_showAliasInfo (other->sref);
10229 if (sRef_hasAliasInfoLoc (res->sref)) {
10230 llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc);
10231 sRef_showAliasInfo (res->sref);
10235 sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
10236 sRef_setDefinedComplete (res->sref, fileloc_undefined);
10238 sRef_setAliasKind (other->sref, AK_ERROR, fileloc_undefined);
10239 sRef_setDefinedComplete (other->sref, fileloc_undefined);
10244 ** A reference is relevant for certain checks, only if it
10245 ** is not definitely null on this path (but not declared
10246 ** to always be null.)
10249 static bool uentry_relevantReference (sRef sr, bool flip)
10251 if (sRef_isKept (sr) || sRef_isDependent (sr))
10259 return !sRef_definitelyNullContext (sr);
10263 return !sRef_definitelyNullAltContext (sr);
10269 uentry_mergeAliasStates (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other,
10270 fileloc loc, bool mustReturn, bool flip, bool opt,
10273 sRef rs = res->sref;
10274 sRef os = other->sref;
10276 DPRINTF (("Merge alias states: %s / %s",
10277 uentry_unparseFull (res),
10278 uentry_unparseFull (other)));
10280 if (sRef_isValid (rs))
10284 if (uentry_incompatibleMemoryStates (rs, os))
10286 DPRINTF (("Incompatible: \n\t%s / \n\t%s",
10287 sRef_unparseFull (rs), sRef_unparseFull (os)));
10289 if (sRef_isThroughArrayFetch (rs)
10290 && !context_getFlag (FLG_STRICTBRANCHSTATE))
10292 if (sRef_isKept (rs) || sRef_isKept (os))
10294 sRef_maybeKill (rs, loc);
10296 else if (sRef_isPossiblyDead (os))
10298 sRef_maybeKill (rs, loc);
10307 if (uentry_relevantReference (os, flip))
10309 if (sRef_isLocalParamVar (rs)
10310 && (sRef_isLocalState (os)
10311 || sRef_isDependent (os)))
10313 if (sRef_isDependent (rs))
10315 sRef_setDependent (os, loc);
10319 sRef_setDefState (rs, SS_UNUSEABLE, loc);
10324 branchStateError (res, other, !flip, cl, loc); /* evans 2002-12-15: changed flip to !flip */
10329 if (sRef_isKept (rs))
10331 DPRINTF (("Setting kept: %s", sRef_unparseFull (os)));
10332 sRef_setKept (os, loc);
10337 if (uentry_incompatibleMemoryStates (os, rs))
10339 if (uentry_relevantReference (rs, !flip))
10341 if (sRef_isLocalParamVar (rs)
10342 && (sRef_isDependent (rs)
10343 || sRef_isLocalState (rs)))
10345 if (sRef_isDependent (os))
10347 sRef_setDependent (rs, loc);
10351 sRef_setDefState (rs, SS_UNUSEABLE, loc);
10356 if (sRef_isParam (os))
10359 ** If the local variable associated
10360 ** with the param has the correct state,
10362 ** (e.g., free (s); s = new(); ...
10365 uentry uvar = usymtab_lookupSafe (other->uname);
10367 if (uentry_isValid (uvar)
10368 && ((sRef_isDead (os)
10369 && sRef_isOnly (uvar->sref))
10370 || (sRef_isDependent (os)
10371 && sRef_isOwned (uvar->sref))))
10377 branchStateAltError (res, other,
10383 DPRINTF (("Here: %s / %s",
10384 uentry_unparseFull (res),
10385 uentry_unparseFull (other)));
10387 branchStateAltError (res, other,
10394 if (sRef_isKept (os))
10396 sRef_setKept (rs, loc);
10402 DPRINTF (("Merge opt..."));
10403 sRef_mergeOptState (rs, os, cl, loc);
10404 DPRINTF (("Done!"));
10408 DPRINTF (("Merging states: \n\t%s / \n\t%s", sRef_unparseFull (rs), sRef_unparseFull (os)));
10409 sRef_mergeState (rs, os, cl, loc);
10410 DPRINTF (("After merging : \n\t%s / \n\t%s", sRef_unparseFull (rs), sRef_unparseFull (os)));
10415 if (sRef_isModified (os))
10417 sRef_setModified (rs);
10422 DPRINTF (("After merge: %s", sRef_unparseFull (res->sref)));
10426 uentry_mergeValueStates (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other,
10427 fileloc loc, bool mustReturn, /*@unused@*/ bool flip)
10429 valueTable rvalues;
10430 valueTable ovalues;
10432 DPRINTF (("Merge values: %s / %s", sRef_unparseFull (res->sref), sRef_unparseFull (other->sref)));
10440 rvalues = sRef_getValueTable (res->sref);
10441 ovalues = sRef_getValueTable (other->sref);
10443 if (valueTable_isUndefined (ovalues))
10445 DPRINTF (("No value table: %s", sRef_unparseFull (other->sref)));
10448 else if (valueTable_isUndefined (rvalues))
10451 ** Copy values from other
10458 valueTable_elements (ovalues, fkey, fval) {
10460 metaStateInfo minfo;
10461 stateCombinationTable sctable;
10465 tval = valueTable_lookup (rvalues, fkey);
10467 DPRINTF (("Merge value: %s / %s X %s", fkey,
10468 stateValue_unparse (fval), stateValue_unparse (tval)));
10470 minfo = context_lookupMetaStateInfo (fkey);
10471 llassert (stateValue_isDefined (tval));
10473 if (metaStateInfo_isUndefined (minfo) || !stateValue_isDefined (tval))
10475 DPRINTF (("Cannot find meta state for: %s", fkey));
10480 llassert (metaStateInfo_isDefined (minfo));
10482 if (stateValue_isError (fval)
10483 || sRef_definitelyNullContext (res->sref))
10485 sRef_setMetaStateValueComplete (res->sref,
10486 fkey, stateValue_getValue (fval),
10487 stateValue_getLoc (fval));
10488 DPRINTF (("Setting res: %s", sRef_unparseFull (res->sref)));
10490 else if (stateValue_isError (tval)
10491 || sRef_definitelyNullAltContext (other->sref))
10493 DPRINTF (("Other branch is definitely null!"));
10495 else if (sRef_isStateUndefined (res->sref)
10496 || sRef_isDead (res->sref))
10498 ; /* Combination state doesn't matter if it is undefined or dead */
10502 DPRINTF (("Check: %s / %s / %s / %s", fkey,
10503 metaStateInfo_unparse (minfo),
10504 stateValue_unparse (fval),
10505 stateValue_unparse (tval)));
10507 DPRINTF (("state values: %d / %d",
10508 stateValue_getValue (fval), stateValue_getValue (tval)));
10510 sctable = metaStateInfo_getMergeTable (minfo);
10512 DPRINTF (("Merge table: %s",
10513 stateCombinationTable_unparse (sctable)));
10515 msg = cstring_undefined;
10517 nval = stateCombinationTable_lookup (sctable,
10518 stateValue_getValue (fval),
10519 stateValue_getValue (tval),
10522 DPRINTF (("nval: %d / %d / %d", nval,
10523 stateValue_getValue (fval), stateValue_getValue (tval)));
10525 if (nval == stateValue_error)
10527 if (uentry_isGlobalMarker (res))
10532 ("Control branches merge with incompatible global states (%s and %s)%q",
10533 metaStateInfo_unparseValue (minfo, stateValue_getValue (fval)),
10534 metaStateInfo_unparseValue (minfo, stateValue_getValue (tval)),
10535 cstring_isDefined (msg)
10536 ? message (": %s", msg) : cstring_undefined),
10539 sRef_showMetaStateInfo (res->sref, fkey);
10540 sRef_showMetaStateInfo (other->sref, fkey);
10548 ("Control branches merge with incompatible states for %q (%s and %s)%q",
10549 uentry_getName (res),
10550 metaStateInfo_unparseValue (minfo, stateValue_getValue (fval)),
10551 metaStateInfo_unparseValue (minfo, stateValue_getValue (tval)),
10552 cstring_isDefined (msg)
10553 ? message (": %s", msg) : cstring_undefined),
10556 sRef_showMetaStateInfo (res->sref, fkey);
10557 sRef_showMetaStateInfo (other->sref, fkey);
10558 DPRINTF (("Res: %s", sRef_unparseFull (res->sref)));
10559 DPRINTF (("Other: %s", sRef_unparseFull (other->sref)));
10560 DPRINTF (("Null: %s / %s",
10561 bool_unparse (usymtab_isDefinitelyNull (res->sref)),
10562 bool_unparse (usymtab_isDefinitelyNull (other->sref))));
10568 if (nval == stateValue_getValue (fval)
10569 && nval != stateValue_getValue (tval))
10571 loc = stateValue_getLoc (fval);
10573 else if (nval == stateValue_getValue (tval)
10574 && nval != stateValue_getValue (fval))
10576 loc = stateValue_getLoc (tval);
10583 if (stateValue_getValue (sRef_getMetaStateValue (res->sref, fkey)) == nval
10584 && nval == stateValue_getValue (fval)
10585 && nval == stateValue_getValue (tval))
10591 sRef_setMetaStateValueComplete (res->sref, fkey, nval, loc);
10595 } end_valueTable_elements ;
10601 uentry_mergeSetStates (/*@notnull@*/ uentry res,
10602 /*@notnull@*/ uentry other, /*@unused@*/ fileloc loc,
10603 bool flip, clause cl)
10605 if (cl == DOWHILECLAUSE)
10607 res->used = other->used || res->used;
10608 res->lset = other->lset || res->lset;
10609 res->uses = filelocList_append (res->uses, other->uses);
10610 other->uses = filelocList_undefined;
10614 if (sRef_isMacroParamRef (res->sref)
10615 && !uentry_isSefParam (other)
10616 && !uentry_isSefParam (res))
10618 bool hasError = FALSE;
10620 if (bool_equal (res->used, other->used))
10622 res->used = other->used;
10626 if (other->used && !flip)
10631 message ("Macro parameter %q used in true clause, "
10632 "but not in false clause",
10633 uentry_getName (res)),
10634 uentry_whereDeclared (res));
10641 message ("Macro parameter %q used in false clause, "
10642 "but not in true clause",
10643 uentry_getName (res)),
10644 uentry_whereDeclared (res));
10650 /* make it sef now, prevent more errors */
10651 res->info->var->kind = VKREFSEFPARAM;
10657 res->used = other->used || res->used;
10658 res->lset = other->lset || res->lset;
10659 res->uses = filelocList_append (res->uses, other->uses);
10660 other->uses = filelocList_undefined;
10666 uentry_mergeState (uentry res, uentry other, fileloc loc,
10667 bool mustReturn, bool flip, bool opt,
10670 llassert (uentry_isValid (res));
10671 llassert (uentry_isValid (other));
10673 llassert (res->ukind == other->ukind);
10674 llassert (res->ukind == KVAR);
10676 DPRINTF (("Merge state: %s / %s", uentry_unparseFull (res),
10677 uentry_unparseFull (other)));
10679 uentry_mergeAliasStates (res, other, loc, mustReturn, flip, opt, cl);
10680 uentry_mergeValueStates (res, other, loc, mustReturn, flip);
10681 uentry_mergeSetStates (res, other, loc, flip, cl);
10683 DPRINTF (("Merge ==> %s", uentry_unparseFull (res)));
10686 void uentry_setUsed (uentry e, fileloc loc)
10688 static bool firstTime = TRUE;
10689 static bool showUses = FALSE;
10690 static bool exportLocal = FALSE;
10692 DPRINTF (("Used: %s / %s", uentry_unparse (e), fileloc_unparse (loc)));
10696 /* need to track uses is FLG_SHOWUSES or FLG_EXPORTLOCAL is true */
10698 showUses = context_getFlag (FLG_SHOWUSES);
10699 exportLocal = context_maybeSet (FLG_EXPORTLOCAL);
10704 if (uentry_isValid (e))
10706 if (warnClause_isDefined (e->warn))
10708 flagSpec flg = warnClause_getFlag (e->warn);
10711 if (warnClause_hasMessage (e->warn))
10713 msg = cstring_copy (warnClause_getMessage (e->warn));
10717 msg = message ("Use of possibly dangerous %s",
10718 uentry_ekindNameLC (e));
10722 message ("%q: %q", msg, uentry_getName (e)),
10726 if (sRef_isMacroParamRef (e->sref))
10728 if (uentry_isYield (e) || uentry_isSefParam (e))
10734 if (context_inConditional ())
10738 message ("Macro parameter %q used in conditionally "
10739 "executed code (may or may not be "
10740 "evaluated exactly once)",
10741 uentry_getName (e)),
10744 e->info->var->kind = VKREFSEFPARAM;
10753 message ("Macro parameter %q used more than once",
10754 uentry_getName (e)),
10755 uentry_whereDeclared (e)))
10757 e->info->var->kind = VKREFSEFPARAM;
10764 if (usymId_isValid (usymtab_directParamNo (e)))
10766 uentry_setUsed (usymtab_getParam (usymId_toInt (usymtab_directParamNo (e))), loc);
10771 if (!sRef_isLocalVar (e->sref))
10775 e->uses = filelocList_add (e->uses, fileloc_copy (loc));
10781 if (context_inMacro ())
10783 e->uses = filelocList_addUndefined (e->uses);
10787 e->uses = filelocList_addDifferentFile
10789 uentry_whereDeclared (e),
10798 bool uentry_isReturned (uentry u)
10800 return (uentry_isValid (u) && uentry_isVar (u)
10801 && (u->info->var->kind == VKRETPARAM
10802 || u->info->var->kind == VKSEFRETPARAM));
10805 /*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args, fileloc loc)
10807 llassert (uentry_isRealFunction (u));
10809 if (ctype_isFunction (u->utype) && sRef_isStateSpecial (uentry_getSref (u)))
10811 stateClauseList clauses = uentry_getStateClauseList (u);
10812 sRef res = sRef_makeNew (ctype_getReturnType (u->utype), u->sref, u->uname);
10814 DPRINTF (("Returned: %s", sRef_unparseFull (res)));
10815 sRef_setAllocated (res, loc);
10817 DPRINTF (("ensures clause: %s / %s", uentry_unparse (u),
10818 stateClauseList_unparse (clauses)));
10821 ** This should be in exprNode_reflectEnsuresClause
10824 stateClauseList_postElements (clauses, cl)
10826 if (!stateClause_isGlobal (cl))
10828 sRefSet refs = stateClause_getRefs (cl);
10829 sRefMod modf = stateClause_getEffectFunction (cl);
10831 sRefSet_elements (refs, el)
10833 sRef base = sRef_getRootBase (el);
10835 if (sRef_isResult (base))
10839 sRef sr = sRef_fixBase (el, res);
10847 } end_sRefSet_elements ;
10849 } end_stateClauseList_postElements ;
10857 sRefSet prefs = sRefSet_new ();
10858 sRef res = sRef_undefined;
10861 params = uentry_getParams (u);
10863 uentryList_elements (params, current)
10865 if (uentry_isReturned (current))
10867 if (exprNodeList_size (args) >= paramno)
10869 exprNode ecur = exprNodeList_nth (args, paramno);
10870 sRef tref = exprNode_getSref (ecur);
10872 DPRINTF (("Returned reference: %s", sRef_unparseFull (tref)));
10874 if (sRef_isValid (tref))
10876 sRef tcref = sRef_copy (tref);
10878 usymtab_addForceMustAlias (tcref, tref); /* evans 2001-05-27 */
10880 if (sRef_isNew (tcref))
10882 /* tcref->kind = SK_OBJECT; */ /*!! Not new anymore */
10885 if (sRef_isDead (tcref))
10887 sRef_setDefined (tcref, loc);
10888 sRef_setOnly (tcref, loc);
10891 if (sRef_isRefCounted (tcref))
10893 /* could be a new ref now (but only if its returned) */
10894 sRef_setAliasKindComplete (tcref, AK_ERROR, loc);
10897 sRef_makeSafe (tcref);
10898 DPRINTF (("Returns tcref / %s", sRef_unparseFull (tcref)));
10899 prefs = sRefSet_insert (prefs, tcref);
10905 } end_uentryList_elements ;
10907 if (sRefSet_size (prefs) > 0)
10909 nstate n = sRef_getNullState (u->sref);
10911 if (sRefSet_size (prefs) == 1)
10913 res = sRefSet_choose (prefs);
10917 /* should this ever happen? */
10918 res = sRefSet_mergeIntoOne (prefs);
10921 if (nstate_isKnown (n))
10923 sRef_setNullState (res, n, loc);
10928 if (ctype_isFunction (u->utype))
10930 DPRINTF (("Making new from %s -->", uentry_unparseFull (u)));
10931 res = sRef_makeNew (ctype_getReturnType (u->utype), u->sref, u->uname);
10935 res = sRef_makeNew (ctype_unknown, u->sref, u->uname);
10938 if (sRef_isRefCounted (res))
10940 sRef_setAliasKind (res, AK_NEWREF, loc);
10945 if (sRef_getNullState (res) == NS_ABSNULL)
10947 ctype ct = ctype_realType (u->utype);
10949 if (ctype_isAbstract (ct))
10951 sRef_setNotNull (res, loc);
10955 if (ctype_isUser (ct))
10957 sRef_setStateFromUentry (res, usymtab_getTypeEntry (ctype_typeId (ct)));
10961 sRef_setNotNull (res, loc);
10966 if (sRef_isRefCounted (res))
10968 sRef_setAliasKind (res, AK_NEWREF, loc);
10970 else if (sRef_isKillRef (res))
10972 sRef_setAliasKind (res, AK_REFCOUNTED, loc);
10979 ak = sRef_getAliasKind (res);
10981 if (alkind_isImplicit (ak))
10983 sRef_setAliasKind (res,
10984 alkind_fixImplicit (ak),
10988 sRefSet_free (prefs);
10991 if (sRef_isOnly (res))
10993 sRef_setFresh (res, loc);
10997 DPRINTF (("Returns ref: %s", sRef_unparseFull (res)));
11002 static bool uentry_isRefCounted (uentry ue)
11004 ctype ct = uentry_getType (ue);
11006 if (ctype_isFunction (ct))
11008 return (ctype_isRefCounted (ctype_getReturnType (ct)));
11012 return (ctype_isRefCounted (ct));
11017 ** old was declared yield in the specification.
11018 ** new is declared in the iter implementation.
11021 void uentry_checkYieldParam (uentry old, uentry unew)
11025 llassert (uentry_isVariable (old));
11026 llassert (uentry_isVariable (unew));
11028 unew->info->var->kind = VKYIELDPARAM;
11029 (void) checkTypeConformance (old, unew, TRUE);
11030 checkVarConformance (old, unew, TRUE, FALSE);
11032 /* get rid of param marker */
11034 name = uentry_getName (unew);
11035 cstring_free (unew->uname);
11036 unew->uname = name;
11037 unew->info->var->kind = VKREFYIELDPARAM;
11039 uentry_setUsed (old, fileloc_undefined);
11040 uentry_setUsed (unew, fileloc_undefined);
11043 /*@observer@*/ cstring
11044 uentry_ekindName (uentry ue)
11046 if (uentry_isValid (ue))
11051 return cstring_makeLiteralTemp ("<Error: invalid uentry>");
11053 return cstring_makeLiteralTemp ("Datatype");
11055 return cstring_makeLiteralTemp ("Enum member");
11057 return cstring_makeLiteralTemp ("Constant");
11059 if (uentry_isParam (ue))
11061 return cstring_makeLiteralTemp ("Parameter");
11063 else if (uentry_isExpandedMacro (ue))
11065 return cstring_makeLiteralTemp ("Expanded macro");
11069 return cstring_makeLiteralTemp ("Variable");
11072 return cstring_makeLiteralTemp ("Function");
11074 return cstring_makeLiteralTemp ("Iterator");
11076 return cstring_makeLiteralTemp ("Iterator finalizer");
11078 return cstring_makeLiteralTemp ("Struct tag");
11080 return cstring_makeLiteralTemp ("Union tag");
11082 return cstring_makeLiteralTemp ("Enum tag");
11084 return cstring_makeLiteralTemp ("Optional parameters");
11089 return cstring_makeLiteralTemp ("<Undefined>");
11095 /*@observer@*/ cstring
11096 uentry_ekindNameLC (uentry ue)
11098 if (uentry_isValid (ue))
11103 return cstring_makeLiteralTemp ("<error: invalid uentry>");
11105 return cstring_makeLiteralTemp ("datatype");
11107 return cstring_makeLiteralTemp ("enum member");
11109 return cstring_makeLiteralTemp ("constant");
11111 if (uentry_isParam (ue))
11113 return cstring_makeLiteralTemp ("parameter");
11115 else if (uentry_isExpandedMacro (ue))
11117 return cstring_makeLiteralTemp ("expanded macro");
11121 return cstring_makeLiteralTemp ("variable");
11124 return cstring_makeLiteralTemp ("function");
11126 return cstring_makeLiteralTemp ("iterator");
11128 return cstring_makeLiteralTemp ("iterator finalizer");
11130 return cstring_makeLiteralTemp ("struct tag");
11132 return cstring_makeLiteralTemp ("union tag");
11134 return cstring_makeLiteralTemp ("enum tag");
11136 return cstring_makeLiteralTemp ("optional parameters");
11141 return cstring_makeLiteralTemp ("<Undefined>");
11147 void uentry_setHasNameError (uentry ue)
11149 llassert (uentry_isValid (ue));
11151 ue->hasNameError = TRUE;
11154 void uentry_checkName (uentry ue)
11156 DPRINTF (("Checking name: %s / %s / %s", uentry_unparse (ue),
11157 uentry_observeRealName (ue),
11158 bool_unparse (uentry_isVisibleExternally (ue))));
11160 if (uentry_isValid (ue)
11161 && !context_inXHFile ()
11162 && uentry_hasName (ue)
11163 && !uentry_isElipsisMarker (ue)
11164 && context_getFlag (FLG_NAMECHECKS)
11165 && !ue->hasNameError
11166 && !uentry_isEndIter (ue)
11167 && !fileloc_isBuiltin (uentry_whereLast (ue))
11168 && (uentry_isExpandedMacro (ue) || !uentry_isForward (ue)))
11170 DPRINTF (("Here..."));
11172 if (uentry_isPriv (ue))
11174 ; /* any checks here? */
11176 else if (fileloc_isExternal (uentry_whereDefined (ue)))
11178 ; /* no errors for externals */
11184 if (uentry_isExpandedMacro (ue))
11190 if (uentry_isExpandedMacro (ue))
11194 else if (uentry_isVariable (ue))
11196 sRef sr = uentry_getSref (ue);
11198 if (sRef_isValid (sr))
11200 scope = sRef_getScope (sr);
11207 else if (uentry_isFunction (ue)
11208 || uentry_isIter (ue)
11209 || uentry_isEndIter (ue)
11210 || uentry_isConstant (ue))
11212 scope = uentry_isStatic (ue) ? fileScope : globScope;
11214 else /* datatypes, etc. must be global */
11219 usymtab_checkDistinctName (ue, scope);
11222 if (context_getFlag (FLG_CPPNAMES))
11227 if (scope == globScope)
11229 checkExternalName (ue);
11231 else if (scope == fileScope)
11233 checkFileScopeName (ue);
11237 checkLocalName (ue);
11241 checkAnsiName (ue);
11246 /*@exposed@*/ uentry uentry_makeUnrecognized (cstring c, /*@only@*/ fileloc loc)
11252 ** Can't but unrecognized ids in macros in global scope, because srefs will break!
11255 if (!context_inMacro ())
11257 sRef_setGlobalScopeSafe ();
11260 ue = uentry_makeVariable (c, ctype_unknown, loc, FALSE);
11261 uentry_setUsed (ue, loc);
11263 tloc = fileloc_createExternal ();
11264 uentry_setDefined (ue, tloc);
11265 fileloc_free (tloc);
11266 uentry_setHasNameError (ue);
11268 if (context_getFlag (FLG_REPEATUNRECOG) || (context_inOldStyleScope()))
11270 uentry_markOwned (ue);
11274 ue = usymtab_supReturnFileEntry (ue);
11277 if (!context_inMacro ())
11279 sRef_clearGlobalScopeSafe ();
11285 uentry uentry_makeGlobalMarker ()
11290 llassert (sRef_inGlobalScope ());
11292 ue = uentry_makeVariableAux
11293 (GLOBAL_MARKER_NAME, ctype_unknown, fileloc_undefined,
11294 sRef_makeGlobalMarker (),
11297 tloc = fileloc_createExternal ();
11298 uentry_setUsed (ue, tloc);
11299 uentry_setDefined (ue, tloc);
11300 fileloc_free (tloc);
11301 uentry_setHasNameError (ue);
11307 bool uentry_isGlobalMarker (uentry ue)
11309 return (uentry_isValid (ue)
11310 && (cstring_equal (uentry_rawName (ue), GLOBAL_MARKER_NAME)));
11313 /* new start modifications */
11315 /* start modifications */
11317 requires: p_e is defined, is a ptr/array variable
11319 effects: sets the state of the variable
11323 void uentry_setPossiblyNullTerminatedState (uentry p_e)
11325 llassert (uentry_isValid (p_e));
11327 if (p_e->info != NULL)
11329 if (p_e->info->var != NULL)
11331 llassert (p_e->info->var->bufinfo != NULL);
11332 p_e->info->var->bufinfo->bufstate = BB_POSSIBLYNULLTERMINATED;
11333 sRef_setPossiblyNullTerminatedState (p_e->sref);
11339 requires: p_e is defined, is a ptr/array variable
11341 effects: sets the size of the buffer
11344 void uentry_setNullTerminatedState (uentry p_e) {
11345 llassert (uentry_isValid (p_e));
11347 if (p_e->info != NULL)
11349 if (p_e->info->var != NULL)
11351 llassert (p_e->info->var->bufinfo != NULL);
11352 p_e->info->var->bufinfo->bufstate = BB_NULLTERMINATED;
11353 sRef_setNullTerminatedState (p_e->sref);
11359 requires: p_e is defined, is a ptr/array variable
11361 effects: sets the size of the buffer
11364 void uentry_setSize (uentry p_e, int size)
11366 if (uentry_isValid (p_e))
11368 if (p_e->info != NULL)
11370 if (p_e->info->var != NULL)
11372 llassert (p_e->info->var->bufinfo != NULL);
11373 p_e->info->var->bufinfo->size = size;
11374 sRef_setSize (p_e->sref, size);
11381 requires: p_e is defined, is a ptr/array variable
11383 effects: sets the length of the buffer
11386 void uentry_setLen (uentry p_e, int len)
11388 if (uentry_isValid (p_e))
11390 if (p_e->info != NULL
11391 && p_e->info->var != NULL)
11393 llassert (p_e->info->var->bufinfo != NULL);
11394 p_e->info->var->bufinfo->len = len;
11395 sRef_setLen (p_e->sref, len);
11402 bool uentry_hasMetaStateEnsures (uentry e)
11404 if (uentry_isValid (e) && uentry_isFunction (e))
11406 return functionConstraint_hasMetaStateConstraint (e->info->fcn->postconditions);
11414 metaStateConstraintList uentry_getMetaStateEnsures (uentry e)
11416 llassert (uentry_isValid (e) && uentry_isFunction (e));
11417 return functionConstraint_getMetaStateConstraints (e->info->fcn->postconditions);
11421 bool uentry_hasBufStateInfo (uentry ue)
11423 llassert (uentry_isValid (ue));
11424 return (ue->info->var->bufinfo != NULL);
11427 bool uentry_isNullTerminated (uentry ue)
11429 llassert (uentry_hasBufStateInfo (ue));
11430 llassert (ue->info->var->bufinfo != NULL);
11431 return ue->info->var->bufinfo->bufstate == BB_NULLTERMINATED;
11434 bool uentry_isPossiblyNullTerminated (uentry ue)
11436 llassert (uentry_hasBufStateInfo (ue));
11437 llassert (ue->info->var->bufinfo != NULL);
11438 return (ue->info->var->bufinfo->bufstate == BB_POSSIBLYNULLTERMINATED);
11441 bool uentry_isNotNullTerminated (uentry ue)
11443 llassert (uentry_hasBufStateInfo (ue));
11444 llassert (ue->info->var->bufinfo != NULL);
11445 return (ue->info->var->bufinfo->bufstate == BB_NOTNULLTERMINATED);
11448 # ifdef DEBUGSPLINT
11451 ** For debugging only
11454 void uentry_checkValid (uentry ue)
11456 if (uentry_isValid (ue))
11458 sRef_checkCompletelyReasonable (ue->sref);