2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 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 lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
28 # include "lclintMacros.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_combineModifies (uentry p_ue, /*@owned@*/ sRefSet p_sr)
49 static void uentry_addStateClause (uentry p_ue, /*@only@*/ stateClause p_sc)
53 static void checkAliasState (/*@notnull@*/ uentry p_old,
54 /*@notnull@*/ uentry p_unew,
55 bool p_mustConform, bool p_completeConform)
56 /*@modifies p_old, p_unew@*/ ;
57 static void checkNullState (/*@notnull@*/ uentry p_old,
58 /*@notnull@*/ uentry p_unew,
59 bool p_mustConform, bool p_completeConform)
60 /*@modifies p_old, p_unew@*/ ;
62 static void checkVarConformance (/*@notnull@*/ uentry p_old,
63 /*@notnull@*/ uentry p_unew,
64 bool p_mustConform, bool p_completeConform)
65 /*@modifies p_old, p_unew@*/;
68 static void uentry_setHasMods (uentry p_ue) /*@modifies p_ue@*/;
69 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_msgstream@*/ ;
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 /*@out@*/ /*@notnull@*/ uentry uentry_alloc (void) /*@*/
95 uentry ue = (uentry) dmalloc (sizeof (*ue));
96 ue->warn = warnClause_undefined; /*@i32@*/
103 static cstring uentry_getOptName (uentry p_e) /*@*/ ;
104 static void uentry_copyInto (/*@out@*/ /*@unique@*/ uentry p_unew, uentry p_old);
105 static void uentry_setNullState (/*@notnull@*/ uentry p_ue, nstate p_ns);
106 static void uentry_setAliasKind (/*@notnull@*/ uentry p_ue, alkind p_ak);
107 static /*@only@*/ /*@null@*/ uinfo uinfo_copy (uinfo p_u, ekind p_kind);
108 static void uinfo_free (/*@only@*/ uinfo p_u, ekind p_kind);
109 static void uvinfo_free (/*@only@*/ uvinfo p_u);
113 static /*@only@*/ cstring ancontext_unparse (ancontext an)
117 case AN_UNKNOWN: return cstring_makeLiteral ("unknown");
118 case AN_FCNRETURN: return cstring_makeLiteral ("return value");
119 case AN_FCNPARAM: return cstring_makeLiteral ("function param");
120 case AN_SUFIELD: return cstring_makeLiteral ("su field");
121 case AN_TDEFN: return cstring_makeLiteral ("type definition");
122 case AN_GSVAR: return cstring_makeLiteral ("global/static var");
123 case AN_CONST: return cstring_makeLiteral ("constant");
129 static int annots[AN_LAST][QU_LAST];
130 static int decls[AN_LAST];
131 static int shdecls[AN_LAST];
132 static int idecls[AN_LAST];
138 for (i = AN_UNKNOWN; i < AN_LAST; i++)
144 for (j = QU_UNKNOWN; j < QU_LAST; j++)
151 static void tallyAnnot (ancontext ac, qual q)
165 for (j = QU_UNKNOWN; j < QU_LAST; j++)
170 for (i = AN_UNKNOWN; i < AN_LAST; i++)
176 printf ("Context: %s (%d declarations, %d sharable, %d indirect)\n",
177 ancontext_unparse (i),
178 decls[i], shdecls[i], idecls[i]);
180 totdecls += decls[i];
181 totshdecls += shdecls[i];
182 totidecls += idecls[i];
184 for (j = QU_UNKNOWN; j < QU_LAST; j++)
186 total[j] += annots[i][j];
187 alltotals += annots[i][j];
190 printf (" Allocation:\n");
194 for (j = QU_UNKNOWN; j < QU_LAST; j++)
196 if (qual_isAliasQual (j) && !qual_isUnique (j))
198 if (annots[i][j] > 0)
200 printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
201 100.0 * (double)annots[i][j] / (double)decls[i]);
202 tmptot += annots[i][j];
207 printf (" Exposure:\n");
211 for (j = QU_UNKNOWN; j < QU_LAST; j++)
213 if (qual_isExQual (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 (" Definition:\n");
226 for (j = QU_UNKNOWN; j < QU_LAST; j++)
228 if (qual_isAllocQual (j))
230 if (annots[i][j] > 0)
232 printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
233 100.0 * (double)annots[i][j] / (double)decls[i]);
240 for (j = QU_UNKNOWN; j < QU_LAST; j++)
242 if (qual_isNull (j) || qual_isNotNull (j) || qual_isRelNull (j))
244 if (annots[i][j] > 0)
246 printf ("\t%10s: %5d (%3.2f%%)\n", qual_unparse (j), annots[i][j],
247 100.0 * (double)annots[i][j] / (double)decls[i]);
256 for (j = QU_UNKNOWN; j < QU_LAST; j++)
260 for (i = AN_UNKNOWN; i < AN_LAST; i++)
262 if (annots[i][j] > 0)
271 printf ("Annotation: %s\n", qual_unparse (j));
273 for (i = AN_UNKNOWN; i < AN_LAST; i++)
275 if (annots[i][j] > 0)
277 printf ("%25s: %5d\n", ancontext_unparse (i), annots[i][j]);
284 printf ("All Contexts\n");
286 for (j = QU_UNKNOWN; j < QU_LAST; j++)
290 printf ("%10s: %5d (%3.2f%%)\n", qual_unparse (j), total[j],
291 100.0 * (double)total[j] / (double)(totdecls));
296 printf ("Total Annotations: %d (%d decls, %d sharable, %d indirect)\n", alltotals, totdecls, totshdecls, totidecls); }
298 extern void uentry_tallyAnnots (uentry u, ancontext kind)
300 alkind ak = sRef_getAliasKind (u->sref);
301 exkind ek = sRef_getExKind (u->sref);
302 nstate ns = sRef_getNullState (u->sref);
303 sstate ss = sRef_getDefState (u->sref);
304 bool recordUnknown = FALSE;
306 if (kind == AN_UNKNOWN)
314 else if (e == KCONST || e == KENUMCONST)
318 else if (e == KFCN || e == KITER)
320 uentryList params = uentry_getParams (u);
323 uentryList_elements (params, current)
325 if (uentry_isReturned (current))
329 if (!uentry_isElipsisMarker (current))
331 uentry_tallyAnnots (current, AN_FCNPARAM);
333 } end_uentryList_elements;
337 if (ctype_isFunction (u->utype)
339 && ctype_isVisiblySharable (ctype_realType (ctype_getReturnType (u->utype))))
341 recordUnknown = TRUE;
344 else if (e == KDATATYPE || e == KSTRUCTTAG || e == KUNIONTAG || e == KENUMTAG)
346 ctype t = ctype_realType (u->utype);
350 uentryList fields = ctype_getFields (t);
352 uentryList_elements (fields, current)
354 uentry_tallyAnnots (current, AN_SUFIELD);
356 } end_uentryList_elements;
360 if (ctype_isVisiblySharable (u->utype))
362 recordUnknown = TRUE;
370 if (ctype_isVisiblySharable (ctype_realType (u->utype)))
372 recordUnknown = TRUE;
379 if (kind == AN_FCNRETURN)
393 if (ctype_isVisiblySharable (ctype_realType (u->utype)))
398 if (ctype_isRealPointer (ctype_realType (u->utype)))
406 case SS_ALLOCATED: tallyAnnot (kind, QU_OUT); break;
407 case SS_PARTIAL: tallyAnnot (kind, QU_PARTIAL); break;
408 case SS_RELDEF: tallyAnnot (kind, QU_RELDEF); break;
409 case SS_SPECIAL: tallyAnnot (kind, QU_SPECIAL); break;
413 if (uentry_isReturned (u))
415 tallyAnnot (kind, QU_RETURNED);
421 if (ctype_isRefCounted (ctype_realType (u->utype))
422 || (ctype_isFunction (u->utype) &&
423 ctype_isRefCounted (ctype_realType (ctype_getReturnType (u->utype)))))
429 if (kind == AN_FCNPARAM)
431 tallyAnnot (kind, QU_TEMP);
433 else if (recordUnknown)
435 if (kind == AN_FCNRETURN)
438 tallyAnnot (kind, QU_UNKNOWN);
442 case AK_ONLY: tallyAnnot (kind, QU_ONLY); break;
443 case AK_IMPONLY: tallyAnnot (kind, QU_ONLY); break;
444 case AK_KEEP: tallyAnnot (kind, QU_KEEP); break;
445 case AK_KEPT: tallyAnnot (kind, QU_KEPT); break;
447 case AK_TEMP: tallyAnnot (kind, QU_TEMP); break;
448 case AK_SHARED: tallyAnnot (kind, QU_SHARED); break;
449 case AK_UNIQUE: tallyAnnot (kind, QU_UNIQUE); break;
450 case AK_RETURNED: tallyAnnot (kind, QU_RETURNED); break;
451 case AK_REFCOUNTED: tallyAnnot (kind, QU_UNKNOWN); break;
452 case AK_REFS: tallyAnnot (kind, QU_REFS); break;
453 case AK_KILLREF: tallyAnnot (kind, QU_KILLREF); break;
454 case AK_NEWREF: tallyAnnot (kind, QU_NEWREF); break;
455 case AK_OWNED: tallyAnnot (kind, QU_OWNED); break;
456 case AK_IMPDEPENDENT:
457 case AK_DEPENDENT: tallyAnnot (kind, QU_DEPENDENT); break;
467 case XO_EXPOSED: tallyAnnot (kind, QU_EXPOSED); break;
468 case XO_OBSERVER: tallyAnnot (kind, QU_OBSERVER); break;
474 case NS_ERROR: break;
475 case NS_UNKNOWN: break;
476 case NS_NOTNULL: break;
477 case NS_MNOTNULL: tallyAnnot (kind, QU_NOTNULL); break;
478 case NS_RELNULL: tallyAnnot (kind, QU_RELNULL); break;
479 case NS_CONSTNULL: tallyAnnot (kind, QU_NULL); break;
480 case NS_POSNULL: tallyAnnot (kind, QU_NULL); break;
482 case NS_ABSNULL: break;
488 static /*@observer@*/ cstring specCode_unparse (specCode s) /*@*/
492 case SPC_NONE: return cstring_makeLiteralTemp ("normal");
493 case SPC_PRINTFLIKE: return cstring_makeLiteralTemp ("printflike");
494 case SPC_SCANFLIKE: return cstring_makeLiteralTemp ("scanflike");
495 case SPC_MESSAGELIKE: return cstring_makeLiteralTemp ("messagelike");
496 case SPC_LAST: return cstring_makeLiteralTemp ("<error>");
502 static specCode specCode_fromInt (int i)
505 llassert (i >= SPC_NONE && i < SPC_LAST);
507 return ((specCode) i);
511 /*@observer@*/ cstring uentry_specOrDefName (uentry u)
513 if (uentry_isDeclared (u))
515 return cstring_makeLiteralTemp ("previously declared");
519 return cstring_makeLiteralTemp ("specified");
523 /*@observer@*/ cstring uentry_specDeclName (uentry u)
525 if (uentry_isDeclared (u))
527 return cstring_makeLiteralTemp ("previous declaration");
531 return cstring_makeLiteralTemp ("specification");
535 static /*@observer@*/ cstring uentry_reDefDecl (uentry old, uentry unew) /*@*/
537 if (uentry_isCodeDefined (old) && uentry_isCodeDefined (unew))
539 return cstring_makeLiteralTemp ("redefined");
541 else if (uentry_isCodeDefined (unew))
543 return cstring_makeLiteralTemp ("defined");
545 else if (uentry_isDeclared (old) && uentry_isDeclared (unew))
547 return cstring_makeLiteralTemp ("redeclared");
551 return cstring_makeLiteralTemp ("declared");
557 /*@only@*/ constraintList uentry_getFcnPreconditions (uentry ue)
559 if (uentry_isValid (ue))
562 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
564 DPRINTF(( (message( "Function pointer %s not doing uentry_getFcnPreconditions", uentry_unparse(ue) )) ));
565 // uentry_makeVarFunction (ue);
568 //llassert (uentry_isFunction (ue));
569 //llassert ((ue->info->fcn->preconditions));
570 //llassert ((ue->info->fcn->preconditions));
572 if (!uentry_isFunction (ue))
574 DPRINTF( (message ("called uentry_getFcnPreconditions on nonfunction %s",
575 uentry_unparse (ue) ) ) );
576 if (!uentry_isSpecified (ue) )
578 DPRINTF((message ("called uentry_getFcnPreconditions on nonfunction %s",
579 uentry_unparse (ue) ) ));
580 return constraintList_undefined;
584 return constraintList_undefined;
587 if (functionConstraint_hasBufferConstraint (ue->info->fcn->preconditions))
589 return constraintList_copy (functionConstraint_getBufferConstraint (ue->info->fcn->preconditions));
598 return constraintList_undefined;
607 constraintList uentry_getFcnPostconditions (uentry ue)
609 if (uentry_isValid (ue))
611 DPRINTF( (message ("called uentry_getFcnPostconditions on %s",
612 uentry_unparse (ue) ) ) );
614 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
616 DPRINTF( (message ("called uentry_getFcnPostconditions on nonfunction %s",
617 uentry_unparse (ue) ) ) );
618 if (!uentry_isFunction (ue) )
620 DPRINTF((message ("called uentry_getFcnPostconditions on nonfunction %s",
621 uentry_unparse (ue) ) ));
622 return constraintList_undefined;
626 return constraintList_undefined;
629 // llassert (uentry_isFunction (ue));
630 if (!uentry_isFunction(ue) )
633 DPRINTF( (message ("called uentry_getFcnPostconditions on non function %s",
634 uentry_unparse (ue) ) ) );
635 return constraintList_undefined;
639 if (functionConstraint_hasBufferConstraint (ue->info->fcn->postconditions))
641 DPRINTF((message ("called uentry_getFcnPostconditions on %s and returned %q",
643 constraintList_unparse (functionConstraint_getBufferConstraint (ue->info->fcn->postconditions)))));
645 return constraintList_copy (functionConstraint_getBufferConstraint (ue->info->fcn->postconditions));
655 return constraintList_undefined;
660 static /*@only@*/ fileloc setLocation (void)
662 fileloc fl = context_getSaveLocation ();
664 if (fileloc_isDefined (fl))
670 return fileloc_copy (g_currentloc);
674 /*@notnull@*/ uentry uentry_makeEnumConstant (cstring n, ctype t)
676 fileloc loc = setLocation ();
677 uentry ue = uentry_makeConstant (n, t, loc);
679 ue->ukind = KENUMCONST;
680 uentry_setDefined (ue, loc);
684 /*@notnull@*/ uentry uentry_makeEnumInitializedConstant (cstring n, ctype t, exprNode expr)
686 fileloc loc = setLocation ();
687 uentry ue = uentry_makeConstant (n, t, loc);
688 ctype etype = exprNode_getType (expr);
690 if (!ctype_isRealInt (etype)) {
694 ("Value of enum member is not an integeral type (type %s): %s",
695 ctype_unparse (etype), exprNode_unparse (expr)),
696 exprNode_loc (expr));
699 ue->ukind = KENUMCONST;
700 uentry_setDefined (ue, loc);
705 /*@notnull@*/ uentry uentry_makeSpecEnumConstant (cstring n, ctype t, fileloc loc)
707 uentry ue = uentry_makeConstant (n, t, loc);
709 ue->ukind = KENUMCONST;
714 /*@notnull@*/ uentry uentry_makeVariableLoc (cstring n, ctype t)
716 return uentry_makeVariable (n, t, setLocation (), FALSE);
720 /*@notnull@*/ /*@only@*/ uentry uentry_makeUnnamedVariable (ctype t)
722 return uentry_makeVariable (cstring_undefined, t, setLocation (), FALSE);
726 /*@notnull@*/ uentry uentry_makeIdDatatype (idDecl id)
728 ctype ct = idDecl_getCtype (id);
729 uentry ue = uentry_makeDatatype (idDecl_observeId (id), ct,
730 MAYBE, MAYBE, setLocation ());
732 uentry_reflectQualifiers (ue, idDecl_getQuals (id));
734 if (!ynm_isOn (ue->info->datatype->abs))
736 if (ctype_isUnknown (ct))
738 ue->info->datatype->mut = MAYBE;
742 ue->info->datatype->mut = ynm_fromBool (ctype_isMutable (ct));
749 void uentry_checkParams (uentry ue)
751 if (uentry_isValid (ue))
753 bool isExt = uentry_isExtern (ue);
755 if (uentry_isRealFunction (ue))
757 uentryList params = uentry_getParams (ue);
759 uentryList_elements (params, current)
761 if (uentry_isValid (current))
763 ctype ct = current->utype;
765 if (ctype_isFixedArray (ct))
767 if (ctype_isArray (ctype_baseArrayPtr (ct))
768 && !ctype_isFixedArray (ctype_baseArrayPtr (ct)))
775 (FLG_FIXEDFORMALARRAY,
776 message ("Function parameter %q declared as "
777 "manifest array (size constant is meaningless)",
778 uentry_getName (current)),
779 uentry_whereDeclared (current));
784 if (ctype_isArray (ct))
788 message ("Function parameter %q declared as "
789 "array (treated as pointer)",
790 uentry_getName (current)),
791 uentry_whereDeclared (current));
795 if (sRef_getNullState (uentry_getSref (current)) == NS_MNOTNULL)
797 if (ctype_isAbstract (ct) &&
798 (isExt || (ctype_isAbstract (ctype_realType (ct))
799 && !context_hasFileAccess (ctype_typeId (ct)))))
804 ("Function %q declared with notnull parameter %q of abstract "
807 uentry_getName (current),
810 ("Since %s is an abstract type, notnull can only be "
811 "used for parameters if the function is static to a "
812 "module where %s is accessible.",
815 uentry_whereDeclared (current));
819 } end_uentryList_elements;
821 if (sRef_getNullState (uentry_getSref (ue)) == NS_MNOTNULL)
823 ctype ct = ue->utype;
825 if (ctype_isAbstract (ct)
826 && (isExt || (ctype_isAbstract (ctype_realType (ct))
827 && !context_hasFileAccess (ctype_typeId (ct)))))
832 ("%s %q declared %s notnull storage of abstract type %s",
833 ekind_capName (uentry_getKind (ue)),
838 ("Since %s is an abstract type, notnull can only be used "
839 "if it is static to a module where %s is accessible.",
842 uentry_whereDeclared (ue));
849 static void reflectImplicitFunctionQualifiers (/*@notnull@*/ uentry ue, bool spec)
851 alkind ak = sRef_getAliasKind (ue->sref);
853 if (alkind_isRefCounted (ak))
855 sRef_setAliasKind (ue->sref, AK_NEWREF, fileloc_undefined);
859 if (alkind_isUnknown (ak))
861 exkind ek = sRef_getExKind (ue->sref);
863 if (exkind_isKnown (ek))
865 DPRINTF (("Setting imp dependent: %s",
866 uentry_unparseFull (ue)));
867 sRef_setAliasKind (ue->sref, AK_IMPDEPENDENT, fileloc_undefined);
871 if (context_getFlag (spec ? FLG_SPECRETIMPONLY : FLG_RETIMPONLY))
873 /* evans 2000-12-22 removed ctype_realType so it will
874 not apply to immutable abstract types. */
876 if (ctype_isVisiblySharable
877 (ctype_realType (ctype_getReturnType (ue->utype))))
879 if (uentryList_hasReturned (uentry_getParams (ue)))
885 if (ctype_isImmutableAbstract (ctype_getReturnType (ue->utype)))
887 ; /* Immutable objects are not shared. */
891 sRef_setAliasKind (ue->sref, AK_IMPONLY,
893 DPRINTF (("Ret imp only: %s",
894 ctype_unparse (ctype_getReturnType (ue->utype))));
904 static /*@notnull@*/ uentry
905 uentry_makeFunctionAux (cstring n, ctype t,
907 /*@only@*/ globSet globs,
908 /*@only@*/ sRefSet mods,
909 /*@only@*/ warnClause warn,
910 /*@keep@*/ fileloc f, bool priv,
911 /*@unused@*/ bool isForward)
913 uentry e = uentry_alloc ();
916 llassert (warnClause_isUndefined (warn)); /*@i325 remove parameter! */
918 if (ctype_isFunction (t))
920 ret = ctype_getReturnType (t);
924 if (ctype_isKnown (t))
926 llbug (message ("not function: %s", ctype_unparse (t)));
933 if (fileloc_isSpec (f) || fileloc_isImport (f))
935 e->whereSpecified = f;
936 e->whereDeclared = fileloc_undefined;
940 e->whereSpecified = fileloc_undefined;
941 e->whereDeclared = f;
944 /* e->shallowCopy = FALSE; */
945 e->uname = cstring_copy (n);
947 e->storageclass = SCNONE;
949 e->sref = sRef_makeType (ret);
951 if (ctype_isUA (ret))
953 sRef_setStateFromType (e->sref, ret);
958 e->uses = filelocList_new ();
960 e->hasNameError = FALSE;
964 e->info = (uinfo) dmalloc (sizeof (*e->info));
965 e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn));
967 e->info->fcn->hasMods = sRefSet_isDefined (mods);
968 e->info->fcn->hasGlobs = globSet_isDefined (globs);
970 e->info->fcn->exitCode = XK_UNKNOWN;
971 e->info->fcn->nullPred = qual_createUnknown ();
972 e->info->fcn->specialCode = SPC_NONE;
974 e->info->fcn->access = access;
975 e->info->fcn->globs = globs;
976 e->info->fcn->defparams = uentryList_undefined;
978 sRef_setDefined (e->sref, f);
979 e->whereDefined = fileloc_undefined;
981 e->info->fcn->mods = sRefSet_undefined;
982 e->info->fcn->specclauses = NULL;
985 e->info->fcn->preconditions = NULL;
989 e->info->fcn->postconditions = NULL;
992 checkGlobalsModifies (e, mods);
993 e->info->fcn->mods = mods;
998 static void uentry_reflectClauses (uentry ue, functionClauseList clauses)
1000 functionClauseList_elements (clauses, el)
1002 DPRINTF (("Reflect clause: %s on %s",
1003 functionClause_unparse (el), uentry_getName (ue)));
1005 if (functionClause_isNoMods (el))
1007 modifiesClause mel = functionClause_getModifies (el);
1009 if (uentry_hasGlobs (ue))
1014 ("No globals and modifies inconsistent to globals clause for %q: %q",
1015 uentry_getName (ue),
1016 globSet_unparse (uentry_getGlobs (ue))),
1017 modifiesClause_getLoc (mel));
1021 if (uentry_hasMods (ue))
1026 ("No globals and modifies inconsistent to modifies clause for %q: %q",
1027 uentry_getName (ue),
1028 sRefSet_unparse (uentry_getMods (ue))),
1029 modifiesClause_getLoc (mel));
1032 uentry_setGlobals (ue, globSet_undefined);
1033 uentry_setModifies (ue, sRefSet_undefined);
1035 else if (functionClause_isGlobals (el))
1037 globalsClause glc = functionClause_getGlobals (el);
1039 DPRINTF (("Globals: %s / %s", uentry_unparse (ue),
1040 globalsClause_unparse (glc)));
1042 if (uentry_hasGlobs (ue))
1047 ("Multiple globals clauses for %q: %q",
1048 uentry_getName (ue),
1049 globalsClause_unparse (glc)),
1050 globalsClause_getLoc (glc));
1051 uentry_setGlobals (ue, globalsClause_takeGlobs (glc)); /*@i32@*/
1055 uentry_setGlobals (ue, globalsClause_takeGlobs (glc));
1058 else if (functionClause_isModifies (el))
1060 modifiesClause mlc = functionClause_getModifies (el);
1062 DPRINTF (("Has modifies: %s", uentry_unparseFull (ue)));
1064 if (uentry_hasMods (ue))
1072 ("Multiple modifies clauses for %s: %s",
1073 uentry_getName (ue),
1074 modifiesClause_unparse (mlc)),
1075 modifiesClause_getLoc (mlc)))
1077 llhint (message ("Previous modifies clause: ",
1078 sRefSet_unparse (uentry_getMods (ue))));
1084 uentry_combineModifies (ue, modifiesClause_takeMods (mlc)); /*@i32@*/
1088 uentry_setModifies (ue, modifiesClause_takeMods (mlc));
1091 else if (functionClause_isEnsures (el))
1093 functionConstraint cl = functionClause_takeEnsures (el);
1094 DPRINTF (("Setting post: %s / %s",
1095 uentry_unparse (ue), functionConstraint_unparse (cl)));
1096 uentry_setPostconditions (ue, cl);
1098 else if (functionClause_isRequires (el))
1100 functionConstraint cl = functionClause_takeRequires (el);
1101 uentry_setPreconditions (ue, cl);
1103 else if (functionClause_isState (el))
1105 stateClause sc = functionClause_takeState (el);
1106 uentry_addStateClause (ue, sc);
1108 else if (functionClause_isWarn (el))
1110 warnClause wc = functionClause_takeWarn (el);
1111 uentry_addWarning (ue, wc);
1115 DPRINTF (("Unhandled clause: %s", functionClause_unparse (el)));
1117 } end_functionClauseList_elements ;
1119 stateClauseList_checkAll (ue);
1122 /*@notnull@*/ uentry uentry_makeIdFunction (idDecl id)
1124 bool leaveFunc = FALSE;
1126 uentry_makeFunction (idDecl_observeId (id), idDecl_getCtype (id),
1127 typeId_invalid, globSet_undefined,
1128 sRefSet_undefined, warnClause_undefined,
1132 ** This makes parameters names print out correctly.
1133 ** (But we might be a local variable declaration for a function type...)
1136 if (context_inFunctionLike ())
1138 DPRINTF (("Header: %s / %s",
1139 uentry_unparse (context_getHeader ()),
1140 idDecl_unparse (id)));
1144 context_enterFunctionDeclaration (ue);
1148 uentry_reflectQualifiers (ue, idDecl_getQuals (id));
1149 reflectImplicitFunctionQualifiers (ue, FALSE);
1151 uentry_reflectClauses (ue, idDecl_getClauses (id));
1153 if (!uentry_isStatic (ue)
1154 && cstring_equalLit (ue->uname, "main"))
1156 ctype typ = ue->utype;
1160 llassert (ctype_isFunction (typ));
1162 retval = ctype_getReturnType (typ);
1164 if (!ctype_isInt (retval))
1168 message ("Function main declared to return %s, should return int",
1169 ctype_unparse (retval)),
1170 uentry_whereDeclared (ue));
1173 args = ctype_argsFunction (typ);
1175 if (uentryList_isMissingParams (args)
1176 || uentryList_size (args) == 0)
1182 if (uentryList_size (args) != 2)
1186 message ("Function main declared with %d arg%&, "
1187 "should have 2 (int argc, char *argv[])",
1188 uentryList_size (args)),
1189 uentry_whereLast (ue));
1193 uentry arg = uentryList_getN (args, 0);
1194 ctype ct = uentry_getType (arg);
1196 if (!ctype_isInt (ct))
1200 message ("Parameter 1, %q, of function main declared "
1201 "with type %t, should have type int",
1202 uentry_getName (arg), ct),
1203 uentry_whereDeclared (arg));
1206 arg = uentryList_getN (args, 1);
1207 ct = uentry_getType (arg);
1209 if (ctype_isArrayPtr (ct)
1210 && ctype_isArrayPtr (ctype_baseArrayPtr (ct))
1211 && ctype_isChar (ctype_baseArrayPtr (ctype_baseArrayPtr (ct))))
1219 message ("Parameter 2, %q, of function main declared "
1220 "with type %t, should have type char **",
1221 uentry_getName (arg), ct),
1222 uentry_whereDeclared (arg));
1230 context_exitFunctionDeclaration ();
1236 static void uentry_implicitParamAnnots (/*@notnull@*/ uentry e)
1238 alkind ak = sRef_getAliasKind (e->sref);
1240 if ((alkind_isUnknown (ak) || alkind_isImplicit (ak))
1241 && context_getFlag (FLG_PARAMIMPTEMP))
1243 exkind ek = sRef_getExKind (e->sref);
1245 if (exkind_isKnown (ek))
1247 DPRINTF (("imp dep: %s", uentry_unparseFull (e)));
1248 sRef_setAliasKind (e->sref, AK_IMPDEPENDENT, fileloc_undefined);
1249 sRef_setOrigAliasKind (e->sref, AK_IMPDEPENDENT);
1253 sRef_setAliasKind (e->sref, AK_IMPTEMP, fileloc_undefined);
1254 sRef_setOrigAliasKind (e->sref, AK_IMPTEMP);
1259 static /*@only@*/ /*@notnull@*/ uentry
1260 uentry_makeVariableParamAux (cstring n, ctype t, /*@dependent@*/ sRef s, sstate defstate) /*@i32 exposed*/
1262 cstring pname = makeParam (n);
1265 DPRINTF (("Sref: %s", sRef_unparseFull (s)));
1266 e = uentry_makeVariableAux (pname, t, setLocation (), s, FALSE, VKPARAM);
1268 cstring_free (pname);
1269 DPRINTF (("Param: %s", uentry_unparseFull (e)));
1270 uentry_implicitParamAnnots (e);
1271 DPRINTF (("Param: %s", uentry_unparseFull (e)));
1273 if (!sRef_isAllocated (e->sref) && !sRef_isPartial (e->sref))
1275 DPRINTF (("Param: %s", uentry_unparseFull (e)));
1276 sRef_setDefState (e->sref, defstate, uentry_whereDeclared (e));
1277 e->info->var->defstate = defstate;
1280 DPRINTF (("Param: %s", uentry_unparseFull (e)));
1286 uentry_setRefCounted (uentry e)
1288 if (uentry_isValid (e))
1290 uentry_setAliasKind (e, AK_REFCOUNTED);
1291 sRef_storeState (e->sref);
1297 uentry_setStatic (uentry c)
1299 if (uentry_isValid (c))
1301 alkind ak = sRef_getAliasKind (c->sref);
1302 c->storageclass = SCSTATIC;
1304 if (uentry_isVariable (c) && !ctype_isFunction (uentry_getType (c)))
1306 if (!alkind_isUnknown (ak)
1307 && !alkind_isStatic (ak))
1309 if (!(ctype_isRealPointer (uentry_getType (c)))
1310 && !(ctype_isAbstract (ctype_realType (uentry_getType (c))))
1311 && !alkind_isRefCounted (ak))
1313 if (alkind_isImplicit (ak)
1314 && alkind_isDependent (ak)
1315 && ctype_isArray (uentry_getType (c)))
1317 ; /* no error for observer arrays */
1323 message ("Static storage %q declared as %s",
1325 alkind_unparse (ak)),
1326 uentry_whereDeclared (c));
1332 if (alkind_isUnknown (ak)
1333 || (alkind_isImplicit (sRef_getAliasKind (c->sref))
1334 && !alkind_isDependent (sRef_getAliasKind (c->sref))))
1336 sRef_setAliasKind (c->sref, AK_STATIC, fileloc_undefined);
1337 sRef_setOrigAliasKind (c->sref, AK_STATIC);
1345 uentry_setExtern (uentry c)
1347 if (uentry_isValid (c))
1348 c->storageclass = SCEXTERN;
1352 uentry_setParamNo (uentry ue, int pno)
1354 llassert (uentry_isAnyParam (ue) && sRef_isParam (ue->sref));
1355 sRef_setParamNo (ue->sref, pno);
1359 void checkGlobalsModifies (/*@notnull@*/ uentry ue, sRefSet sr)
1361 sRefSet_allElements (sr, el)
1363 sRef base = sRef_getRootBase (el);
1365 if (sRef_isFileOrGlobalScope (base) || sRef_isInternalState (base)
1366 || (sRef_isKindSpecial (base) && !sRef_isNothing (base)))
1368 if (!globSet_member (ue->info->fcn->globs, base))
1370 if (uentry_hasGlobs (ue)
1371 || context_getFlag (FLG_WARNMISSINGGLOBALSNOGLOBS))
1374 (FLG_WARNMISSINGGLOBALS,
1376 ("Modifies list for %q uses global %q, "
1377 "not included in globals list.",
1378 uentry_getName (ue),
1379 sRef_unparse (base)),
1380 uentry_whereLast (ue)))
1382 uentry_showWhereSpecified (ue);
1386 ue->info->fcn->globs = globSet_insert (ue->info->fcn->globs,
1388 if (sRef_isFileStatic (base))
1390 context_recordFileGlobals (ue->info->fcn->globs);
1394 } end_sRefSet_allElements;
1398 uentry_makeVariableSrefParam (cstring n, ctype t, /*@exposed@*/ sRef s)
1400 return (uentry_makeVariableParamAux (n, t, s, SS_UNKNOWN));
1404 uentry_fixupSref (uentry ue)
1408 if (uentry_isUndefined (ue) || uentry_isElipsisMarker (ue))
1413 sr = uentry_getSref (ue);
1415 sRef_resetState (sr);
1416 sRef_clearDerived (sr);
1418 llassertprint (uentry_isVariable (ue), ("fixing: %s", uentry_unparseFull (ue)));
1419 llassert (sRef_isValid (sr));
1421 if (uentry_isVariable (ue))
1423 sRef_setDefState (sr, ue->info->var->defstate, fileloc_undefined);
1424 sRef_setNullState (sr, ue->info->var->nullstate, fileloc_undefined);
1428 static void uentry_addStateClause (uentry ue, stateClause sc)
1431 ** Okay to allow multiple clauses of the same kind.
1432 */ /*@i834 is this true?@*/
1434 ue->info->fcn->specclauses =
1435 stateClauseList_add (ue->info->fcn->specclauses, sc);
1437 /* Will call checkAll to check later... */
1440 void uentry_setStateClauseList (uentry ue, stateClauseList clauses)
1442 llassert (uentry_isFunction (ue));
1443 llassert (!stateClauseList_isDefined (ue->info->fcn->specclauses));
1445 DPRINTF (("checked clauses: %s", stateClauseList_unparse (clauses)));
1446 ue->info->fcn->specclauses = clauses;
1447 stateClauseList_checkAll (ue);
1448 DPRINTF (("checked clauses: %s", uentry_unparseFull (ue)));
1452 ** Used for @modifies@ @endmodifies@ syntax.
1454 ** If ue is specified, sr must contain *only*:
1456 ** o file static globals
1457 ** o sRef's derived from modifies spec (i.e., more specific than
1458 ** what was specified)
1460 ** Otherwise, if sr has modifies it must match sr.
1462 ** If it doesn't have modifies, set them to sr.
1466 uentry_checkModifiesContext (void)
1468 if (sRef_modInFunction ())
1472 ("Modifies list not in function context. "
1473 "A modifies list can only appear following the parameter list "
1474 "in a function declaration or header."));
1483 uentry_setModifies (uentry ue, /*@owned@*/ sRefSet sr)
1485 if (!uentry_checkModifiesContext ())
1491 if (uentry_isValid (ue))
1493 if (uentry_isIter (ue))
1495 llassert (sRefSet_isUndefined (ue->info->iter->mods));
1496 ue->info->iter->mods = sr;
1500 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
1502 uentry_makeVarFunction (ue);
1505 llassertfatal (uentry_isFunction (ue));
1506 llassert (sRefSet_isUndefined (ue->info->fcn->mods));
1508 ue->info->fcn->mods = sr;
1509 ue->info->fcn->hasMods = TRUE;
1511 checkGlobalsModifies (ue, sr);
1514 if (context_getFlag (FLG_MODIFIESIMPNOGLOBALS))
1516 ue->info->fcn->hasGlobs = TRUE;
1519 if (sRefSet_hasStatic (ue->info->fcn->mods))
1521 context_recordFileModifies (ue->info->fcn->mods);
1531 uentry_combineModifies (uentry ue, /*@owned@*/ sRefSet sr)
1534 ** Function already has one modifies clause (possibly from
1535 ** a specification).
1538 if (!uentry_checkModifiesContext ())
1543 llassert (uentry_isValid (ue));
1545 if (uentry_isIter (ue))
1547 ue->info->iter->mods = sRefSet_unionFree (ue->info->iter->mods, sr);
1551 llassertfatal (uentry_isFunction (ue));
1552 llassert (ue->info->fcn->hasMods);
1554 checkGlobalsModifies (ue, sr);
1555 ue->info->fcn->mods = sRefSet_unionFree (ue->info->fcn->mods, sr);
1557 if (context_getFlag (FLG_MODIFIESIMPNOGLOBALS))
1559 ue->info->fcn->hasGlobs = TRUE;
1563 if (sRefSet_hasStatic (ue->info->fcn->mods))
1565 context_recordFileModifies (ue->info->fcn->mods);
1569 bool uentry_hasWarning (uentry ue)
1571 return (uentry_isValid (ue)
1572 && warnClause_isDefined (ue->warn));
1575 void uentry_addWarning (uentry ue, /*@only@*/ warnClause warn)
1577 llassert (warnClause_isUndefined (ue->warn));
1582 uentry_setPreconditions (uentry ue, /*@only@*/ functionConstraint preconditions)
1584 if (sRef_modInFunction ())
1587 (message ("Precondition list not in function context. "
1588 "A precondition list can only appear following the parameter list "
1589 "in a function declaration or header."));
1591 /*@-mustfree@*/ return; /*@=mustfree@*/
1594 if (uentry_isValid (ue))
1597 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
1599 uentry_makeVarFunction (ue);
1602 llassertfatal (uentry_isFunction (ue));
1604 if (functionConstraint_isDefined (ue->info->fcn->preconditions))
1606 BADBRANCH; /* should conjoin constraints? */
1608 ue->info->fcn->preconditions = functionConstraint_conjoin (ue->info->fcn->preconditions, preconditions);
1612 ue->info->fcn->preconditions = preconditions;
1619 llfatalbug ( (message("uentry_setPreconditions called with invalid uentry") ));
1628 uentry_setPostconditions (uentry ue, /*@only@*/ functionConstraint postconditions)
1630 if (sRef_modInFunction ())
1633 (message ("Postcondition list not in function context. "
1634 "A postcondition list can only appear following the parameter list "
1635 "in a function declaration or header."));
1637 /*@-mustfree@*/ return; /*@=mustfree@*/
1640 if (uentry_isValid (ue))
1643 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
1645 uentry_makeVarFunction (ue);
1648 llassertfatal (uentry_isFunction (ue));
1650 if (functionConstraint_isUndefined (ue->info->fcn->postconditions))
1652 ue->info->fcn->postconditions = postconditions;
1656 BADBRANCH; /* should conjoin */
1658 ue->info->fcn->postconditions = functionConstraint_conjoin (ue->info->fcn->postconditions, postconditions);
1664 llfatalbug ( (message("uentry_setPostconditions called with invalid uentry") ));
1669 ** requires: new and old are functions
1673 checkGlobalsConformance (/*@notnull@*/ uentry old,
1674 /*@notnull@*/ uentry unew,
1675 bool mustConform, bool completeConform)
1677 bool hasInternalState = FALSE;
1679 old->info->fcn->hasGlobs |= unew->info->fcn->hasGlobs;
1681 if (globSet_isDefined (unew->info->fcn->globs))
1683 globSet_allElements (unew->info->fcn->globs, el)
1685 if (sRef_isFileStatic (el))
1687 sRef sr = globSet_lookup (old->info->fcn->globs, el);
1689 if (sRef_isInvalid (sr))
1691 bool hasError = FALSE;
1693 if (!hasInternalState
1694 && sRef_isInvalid (globSet_lookup (old->info->fcn->globs,
1695 sRef_makeInternalState ()))
1696 && sRef_isInvalid (globSet_lookup (old->info->fcn->globs,
1697 sRef_makeSpecState ())))
1700 && !uentry_isStatic (old)
1703 message ("Globals list for %q includes internal state, %q, "
1704 "but %s without globals internalState.",
1705 uentry_getName (old),
1707 uentry_specOrDefName (old)),
1708 uentry_whereLast (unew)))
1710 uentry_showWhereSpecified (old);
1714 old->info->fcn->globs = globSet_insert (old->info->fcn->globs,
1715 sRef_makeInternalState ());
1716 hasInternalState = TRUE;
1720 && fileloc_sameFile (uentry_whereDeclared (unew),
1721 uentry_whereDeclared (old)))
1726 message ("Function %q inconsistently %rdeclared (in "
1727 "same file) with file static global %q in "
1729 uentry_getName (unew),
1730 uentry_isDeclared (old),
1732 uentry_whereDeclared (unew)))
1734 uentry_showWhereSpecified (old);
1739 old->info->fcn->globs = globSet_insert (old->info->fcn->globs, el);
1740 context_recordFileGlobals (old->info->fcn->globs);
1744 sRef sr = globSet_lookup (old->info->fcn->globs, el);
1746 if (sRef_isInvalid (sr))
1751 message ("Function %q inconsistently %rdeclared with "
1752 "%q in globals list",
1753 uentry_getName (unew),
1754 uentry_isDeclared (old),
1756 uentry_whereDeclared (unew)))
1758 old->info->fcn->globs = globSet_insert (old->info->fcn->globs, el);
1759 uentry_showWhereSpecified (old);
1764 if (!bool_equal (sRef_isAllocated (el), sRef_isAllocated (sr)))
1770 ("Function %q global %q inconsistently "
1771 "%rdeclared as %qout global",
1772 uentry_getName (unew),
1774 uentry_isDeclared (old),
1775 cstring_makeLiteral (sRef_isAllocated (el) ? "" : "non-")),
1776 uentry_whereDeclared (unew)))
1778 uentry_showWhereSpecified (old);
1783 } end_globSet_allElements ;
1785 if (completeConform)
1787 globSet_allElements (old->info->fcn->globs, el)
1789 sRef sr = globSet_lookup (unew->info->fcn->globs, el);
1791 if (sRef_isInvalid (sr))
1794 && uentry_isReallySpecified (old)
1797 message ("Function %q specified with %q in globals list, "
1798 "but declared without %q",
1799 uentry_getName (unew),
1802 uentry_whereDeclared (unew)))
1804 uentry_showWhereSpecified (old);
1807 } end_globSet_allElements;
1812 if (completeConform && !globSet_isEmpty (old->info->fcn->globs))
1814 if (uentry_isReallySpecified (old)
1817 message ("%s %q specified with globals list, but "
1818 "declared with no globals",
1819 ekind_capName (unew->ukind),
1820 uentry_getName (unew)),
1821 uentry_whereDeclared (unew)))
1824 (message ("Specification globals: %q",
1825 globSet_unparse (old->info->fcn->globs)),
1826 uentry_whereSpecified (old));
1830 unew->info->fcn->globs = globSet_copyInto (unew->info->fcn->globs,
1831 old->info->fcn->globs);
1836 ** new modifies list must be included by old modifies list.
1838 ** file static state may be added to new, if old has internal.
1842 checkModifiesConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
1843 bool mustConform, bool completeConform)
1846 bool changedMods = FALSE;
1847 bool modInternal = FALSE;
1849 llassert (uentry_isFunction (old) && uentry_isFunction (unew));
1851 old->info->fcn->hasMods |= unew->info->fcn->hasMods;
1852 newMods = unew->info->fcn->mods;
1854 if (sRefSet_isEmpty (newMods))
1856 if (completeConform && !sRefSet_isEmpty (old->info->fcn->mods)
1857 && uentry_isReallySpecified (old))
1861 message ("%s %q specified with modifies clause, "
1862 "but declared with no modifies clause",
1863 ekind_capName (unew->ukind),
1864 uentry_getName (unew)),
1865 uentry_whereDeclared (unew)))
1867 llgenindentmsg (message ("Specification has modifies %q",
1868 sRefSet_unparse (old->info->fcn->mods)),
1869 uentry_whereSpecified (old));
1876 sRefSet_allElements (newMods, current)
1878 if (sRef_isValid (current))
1880 sRef rb = sRef_getRootBase (current);
1882 if (sRef_isFileStatic (rb))
1886 if (!sRefSet_isSameMember (old->info->fcn->mods,
1887 sRef_makeInternalState ())
1888 && !sRefSet_isSameMember (old->info->fcn->mods,
1889 sRef_makeSpecState ()))
1892 && !uentry_isStatic (old)
1896 ("Modifies list for %q includes internal state, "
1897 "but %s without modifies internal.",
1898 uentry_getName (old),
1899 uentry_specOrDefName (old)),
1900 uentry_whereLast (unew)))
1902 uentry_showWhereSpecified (old);
1905 old->info->fcn->mods =
1906 sRefSet_insert (old->info->fcn->mods,
1907 sRef_makeInternalState ());
1912 old->info->fcn->mods = sRefSet_insert (old->info->fcn->mods,
1918 if (sRef_canModifyVal (current, old->info->fcn->mods))
1920 int size = sRefSet_size (old->info->fcn->mods);
1922 old->info->fcn->mods = sRefSet_insert (old->info->fcn->mods,
1925 if (sRefSet_size (old->info->fcn->mods) != size)
1936 ("Modifies list for %q contains %q, not modifiable "
1938 uentry_getName (old),
1939 sRef_unparse (current),
1940 uentry_specDeclName (old)),
1941 uentry_whereLast (unew)))
1943 uentry_showWhereSpecified (old);
1948 } end_sRefSet_allElements;
1950 if (completeConform && uentry_isReallySpecified (old))
1952 sRefSet_allElements (old->info->fcn->mods, el)
1954 if (sRef_canModify (el, newMods))
1963 ("Specification modifies clause for %q contains %q, "
1964 "not included in declaration modifies clause",
1965 uentry_getName (old),
1967 uentry_whereLast (unew)))
1969 uentry_showWhereSpecified (old);
1972 } end_sRefSet_allElements ;
1976 ** Make sure file static elements will be removed.
1981 context_recordFileModifies (old->info->fcn->mods);
1986 uentry_checkMutableType (uentry ue)
1988 ctype ct = uentry_getType (ue);
1990 if (!ctype_isRealPointer (ct) && !ctype_isRealAbstract (ct))
1992 DPRINTF (("Check mutable: %s", uentry_unparseFull (ue)));
1994 voptgenerror (FLG_MUTREP,
1995 message ("Mutable abstract type %q declared without pointer "
1996 "indirection: %t (violates assignment semantics)",
1997 uentry_getName (ue), ct),
1998 uentry_whereDeclared (ue));
2003 uentry_setMutable (uentry e)
2005 llassert (uentry_isDatatype (e));
2006 e->info->datatype->mut = YES;
2010 uentry_checkIterArgs (uentry ue)
2012 bool hasYield = FALSE;
2015 llassert (uentry_isIter (ue));
2017 args = uentry_getParams (ue);
2019 uentryList_elements (args, el)
2021 sstate ds = uentry_getDefState (el);
2023 if (uentry_isYield (el))
2028 if (sstate_isUnknown (ds))
2030 uentry_setDefState (el, SS_DEFINED);
2036 } end_uentryList_elements;
2040 voptgenerror (FLG_HASYIELD,
2041 message ("Iterator %q declared with no yield parameters",
2042 uentry_getName (ue)),
2043 uentry_whereDeclared (ue));
2048 chkind_fromQual (qual qel)
2050 if (qual_isChecked (qel))
2054 else if (qual_isCheckMod (qel))
2058 else if (qual_isCheckedStrict (qel))
2060 return CH_CHECKEDSTRICT;
2062 else if (qual_isUnchecked (qel))
2064 return CH_UNCHECKED;
2069 /*@notreached@*/ return CH_UNKNOWN;
2074 uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel)
2076 if (qual_isKillRef (qel) || qual_isNewRef (qel) || qual_isTempRef (qel))
2078 if (!uentry_isRefCounted (ue))
2081 (FLG_ANNOTATIONERROR,
2082 message ("Reference counting qualifier %s used on non-reference "
2083 "counted storage: %q",
2085 uentry_unparse (ue)),
2086 uentry_whereLast (ue));
2090 alkind ak = alkind_fromQual (qel);
2092 uentry_setAliasKind (ue, ak);
2095 else if (qual_isRefCounted (qel))
2097 ctype ct = ctype_realType (uentry_getType (ue));
2100 if (ctype_isPointer (ct)
2101 && (ctype_isStruct (rt = ctype_realType (ctype_baseArrayPtr (ct)))))
2103 /* check there is a refs field */
2104 uentryList fields = ctype_getFields (rt);
2105 uentry refs = uentry_undefined;
2107 uentryList_elements (fields, field)
2109 if (uentry_isRefsField (field))
2111 if (uentry_isValid (refs))
2114 (FLG_ANNOTATIONERROR,
2115 message ("Reference counted structure type %s has "
2116 "multiple refs fields: %q and %q",
2118 uentry_getName (refs),
2119 uentry_getName (field)),
2120 uentry_whereLast (field));
2125 } end_uentryList_elements;
2127 if (uentry_isInvalid (refs))
2131 message ("Reference counted structure type %s has "
2133 ctype_unparse (ct)),
2135 ("To count reference, the structure must have a field named "
2136 "refs of type int."),
2139 else if (!ctype_isInt (uentry_getType (refs)))
2142 (FLG_ANNOTATIONERROR,
2143 message ("Reference counted structure type %s refs field has "
2144 "type %s (should be int)", ctype_unparse (ct),
2145 ctype_unparse (uentry_getType (refs))),
2146 uentry_whereLast (refs));
2150 sRef_setAliasKind (ue->sref, alkind_fromQual (qel),
2151 uentry_whereDeclared (ue));
2156 if ((ctype_isPointer (ct)
2157 && ctype_isUnknown (ctype_realType (ctype_baseArrayPtr (ct))))
2158 ||ctype_isAbstract (ct) || ctype_isUnknown (ct))
2160 sRef_setAliasKind (ue->sref, alkind_fromQual (qel),
2161 uentry_whereDeclared (ue));
2166 (FLG_ANNOTATIONERROR,
2167 message ("Non-pointer to structure type %s declared with "
2168 "refcounted qualifier",
2169 ctype_unparse (ct)),
2170 uentry_whereLast (ue));
2174 else if (qual_isRefs (qel))
2176 if (uentry_isVariable (ue) && !uentry_isParam (ue))
2178 uentry_setAliasKind (ue, AK_REFS);
2183 (FLG_ANNOTATIONERROR,
2184 message ("Refs qualifier used on non-structure field: %q",
2185 uentry_unparse (ue)),
2186 uentry_whereLast (ue));
2189 else if (qual_isAliasQual (qel))
2191 alkind ak = alkind_fromQual (qel);
2193 alkind oldak = uentry_getAliasKind (ue);
2194 ctype ut = uentry_getType (ue);
2196 if (alkind_isImplicit (ak)
2197 && (alkind_isKnown (oldak) && !alkind_isImplicit (oldak)))
2199 /* ignore the implied qualifier */
2203 if (uentry_isEitherConstant (ue))
2206 (FLG_ANNOTATIONERROR,
2207 message ("Alias qualifier %s used on constant: %q",
2208 alkind_unparse (ak), uentry_unparse (ue)),
2209 uentry_whereLast (ue));
2214 if (ctype_isFunction (ut))
2216 ut = ctype_getReturnType (ut);
2219 if (!(ctype_isVisiblySharable (ut)
2220 || ctype_isRealArray (ut)
2221 || ctype_isRealSU (ut)))
2223 if (!qual_isImplied (qel))
2226 (FLG_ANNOTATIONERROR,
2227 message ("Alias qualifier %s used on unsharable storage type %t: %q",
2228 alkind_unparse (ak), ut, uentry_getName (ue)),
2229 uentry_whereLast (ue));
2236 if (uentry_isRefCounted (ue))
2238 if (!(qual_isRefQual (qel) || qual_isOnly (qel)
2239 || qual_isExposed (qel)
2240 || qual_isObserver (qel)))
2242 if (!qual_isImplied (qel))
2245 (FLG_ANNOTATIONERROR,
2247 ("Alias qualifier %s used on reference counted storage: %q",
2248 alkind_unparse (ak),
2249 uentry_unparse (ue)),
2250 uentry_whereLast (ue));
2258 if (qual_isRefQual (qel))
2261 (FLG_ANNOTATIONERROR,
2262 message ("Qualifier %s used on non-reference counted storage: %q",
2263 alkind_unparse (ak), uentry_unparse (ue)),
2264 uentry_whereLast (ue));
2273 uentry_setAliasKind (ue, ak);
2276 else if (qual_isNull (qel))
2278 if (uentry_isConstant (ue))
2282 ctype_isAbstract (ue->utype) ? NS_CONSTNULL : NS_DEFNULL,
2283 uentry_whereDeclared (ue));
2287 uentry_setNullState (ue, NS_POSNULL);
2290 else if (qual_isRelNull (qel))
2292 uentry_setNullState (ue, NS_RELNULL);
2294 else if (qual_isNotNull (qel))
2296 uentry_setNullState (ue, NS_MNOTNULL);
2298 else if (qual_isAbstract (qel)
2299 || qual_isConcrete (qel))
2301 if (!uentry_isDatatype (ue))
2304 (FLG_ANNOTATIONERROR,
2305 message ("Qualifier %s used with non-datatype",
2306 qual_unparse (qel)),
2307 uentry_whereLast (ue));
2311 ue->info->datatype->abs = ynm_fromBool (qual_isAbstract (qel));
2314 else if (qual_isMutable (qel))
2316 if (!uentry_isDatatype (ue))
2319 (FLG_ANNOTATIONERROR,
2320 message ("Qualifier %s used with non-datatype", qual_unparse (qel)),
2321 uentry_whereLast (ue));
2325 if (!ynm_isOn (ue->info->datatype->mut))
2327 uentry_checkMutableType (ue);
2330 ue->info->datatype->mut = YES;
2333 else if (qual_isImmutable (qel))
2335 if (!uentry_isDatatype (ue))
2337 voptgenerror (FLG_ANNOTATIONERROR,
2338 message ("Qualifier %s used with non-datatype",
2339 qual_unparse (qel)),
2340 uentry_whereLast (ue));
2344 ue->info->datatype->mut = NO;
2347 else if (qual_isNullPred (qel))
2349 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2351 uentry_makeVarFunction (ue);
2354 if (uentry_isFunction (ue))
2356 ctype typ = uentry_getType (ue);
2357 ctype rtype = ctype_getReturnType (uentry_getType (ue));
2359 if (ctype_isRealBool (rtype))
2361 uentryList pl = ctype_argsFunction (typ);
2363 if (uentryList_size (pl) == 1)
2365 ue->info->fcn->nullPred = qel;
2369 voptgenerror (FLG_ANNOTATIONERROR,
2370 message ("Qualifier %s used with function having %d "
2371 "arguments (should have 1)",
2373 uentryList_size (pl)),
2374 uentry_whereLast (ue));
2379 voptgenerror (FLG_ANNOTATIONERROR,
2380 message ("Qualifier %s used with function returning %s "
2381 "(should return bool)",
2383 ctype_unparse (rtype)),
2384 uentry_whereLast (ue));
2389 voptgenerror (FLG_ANNOTATIONERROR,
2390 message ("Qualifier %s used with non-function",
2391 qual_unparse (qel)),
2392 uentry_whereLast (ue));
2395 else if (qual_isExitQual (qel))
2397 exitkind exk = exitkind_fromQual (qel);
2399 if (uentry_isFunction (ue))
2401 if (exitkind_isKnown (ue->info->fcn->exitCode))
2403 voptgenerror (FLG_ANNOTATIONERROR,
2404 message ("Multiple exit qualifiers used on function %q: %s, %s",
2405 uentry_getName (ue),
2406 exitkind_unparse (ue->info->fcn->exitCode),
2407 exitkind_unparse (exk)),
2408 uentry_whereLast (ue));
2411 ue->info->fcn->exitCode = exk;
2415 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2417 uentry_makeVarFunction (ue);
2418 ue->info->fcn->exitCode = exk;
2422 voptgenerror (FLG_ANNOTATIONERROR,
2423 message ("Exit qualifier %s used with non-function (type %s)",
2425 ctype_unparse (uentry_getType (ue))),
2426 uentry_whereLast (ue));
2430 else if (qual_isMetaState (qel))
2432 annotationInfo ainfo = qual_getAnnotationInfo (qel);
2434 if (annotationInfo_matchesContext (ainfo, ue))
2436 DPRINTF (("Reflecting %s on %s",
2437 annotationInfo_unparse (ainfo),
2438 uentry_unparseFull (ue)));
2440 sRef_reflectAnnotation (ue->sref, ainfo, g_currentloc);
2441 DPRINTF (("==> %s", sRef_unparseFull (ue->sref)));
2442 DPRINTF (("==> %s", uentry_unparseFull (ue)));
2447 (FLG_ANNOTATIONERROR,
2448 message ("Meta state anntation %s used in inconsistent context: %q",
2450 uentry_unparse (ue)),
2451 uentry_whereLast (ue)))
2453 /*@i! annotationInfo_showContextError (ainfo, ue); */
2459 if (qual_isCQual (qel))
2465 llbug (message ("Unhandled qualifier: %s", qual_unparse (qel)));
2471 uentry_reflectQualifiers (uentry ue, qualList q)
2473 llassert (uentry_isValid (ue));
2475 qualList_elements (q, qel)
2477 if (qual_isStatic (qel))
2479 uentry_setStatic (ue);
2481 else if (qual_isUnused (qel))
2483 uentry_setUsed (ue, fileloc_undefined);
2485 else if (qual_isExternal (qel))
2487 fileloc_free (ue->whereDefined);
2488 ue->whereDefined = fileloc_createExternal ();
2490 else if (qual_isSef (qel))
2492 if (uentry_isVariable (ue))
2494 vkind vk = ue->info->var->kind;
2496 llassert (vk != VKREFPARAM);
2498 if (vk == VKYIELDPARAM)
2501 (FLG_ANNOTATIONERROR,
2502 message ("Qualifier sef cannot be used with %s: %q",
2503 cstring_makeLiteralTemp (vk == VKYIELDPARAM ? "yield" : "returned"),
2504 uentry_unparse (ue)),
2505 uentry_whereLast (ue));
2507 else if (vk == VKRETPARAM)
2509 ue->info->var->kind = VKSEFRETPARAM;
2513 ue->info->var->kind = VKSEFPARAM;
2519 (FLG_ANNOTATIONERROR,
2520 message ("Qualifier sef is meaningful only on parameters: %q",
2521 uentry_unparse (ue)),
2522 uentry_whereLast (ue));
2525 else if (qual_isExtern (qel))
2527 ue->storageclass = SCEXTERN;
2529 else if (qual_isGlobalQual (qel)) /* undef, killed */
2531 DPRINTF (("Reflecting qual: %s / %s",
2532 qual_unparse (qel), uentry_unparse (ue)));
2534 if (uentry_isVariable (ue))
2536 sstate oldstate = ue->info->var->defstate;
2537 sstate defstate = sstate_fromQual (qel);
2540 if ((oldstate == SS_UNDEFGLOB && defstate == SS_KILLED)
2541 || (oldstate == SS_KILLED && defstate == SS_UNDEFGLOB))
2543 defstate = SS_UNDEFKILLED;
2550 sRef_setDefState (ue->sref, defstate, fileloc_undefined);
2551 ue->info->var->defstate = defstate;
2556 (FLG_ANNOTATIONERROR,
2557 message ("Qualifier %s used on non-variable: %q",
2558 qual_unparse (qel), uentry_unparse (ue)),
2559 uentry_whereLast (ue));
2562 DPRINTF (("After: %s", uentry_unparseFull (ue)));
2564 /* start modifications */
2565 else if( qual_isBufQualifier(qel) ) {
2566 ctype ct = ctype_realType(uentry_getType(ue));
2567 if( ctype_isArray(ct) || ctype_isPointer(ct) ) {
2569 if( uentry_hasBufStateInfo(ue) ) {
2570 if( qual_isNullTerminated(qel) ) { /* handle Nullterm */
2572 if (uentry_isAnyParam(ue) || uentry_isReturned (ue)) {
2573 /* If formal func param */
2574 uentry_setNullTerminatedState(ue);
2575 uentry_setLen (ue, 1);
2576 uentry_setSize (ue, 1);
2578 sRef_setNullTerminatedState(uentry_getSref(ue));
2579 sRef_setLen (uentry_getSref(ue), 1);
2580 sRef_setSize (uentry_getSref(ue), 1);
2582 uentry_setPossiblyNullTerminatedState(ue);
2584 sRef_setPossiblyNullTerminatedState(uentry_getSref(ue));
2588 /* put other BufState Qualifiers here */
2590 cstring s = uentry_getName(ue);
2591 llfatalbug(message("INTERNAL Error: we have a NULL BufState \
2592 struct for identifier %s\n", s) );
2594 } else if (ctype_isFunction (ct)) { /* We have to handle function */
2596 sRef retSref = uentry_getSref (ue);
2597 ctype retType = sRef_getType (retSref);
2599 if (ctype_isPointer (retType) || ctype_isArray (retType)) {
2600 sRef_setNullTerminatedState (retSref);
2606 message ("Qualifier %s used on non-pointer on \
2607 function return: %q", qual_unparse (qel),
2608 uentry_unparse (ue)));
2615 message ("Qualifier %s used on non-pointer: %q",
2616 qual_unparse (qel), uentry_unparse (ue)));
2618 DPRINTF (("After: %s", uentry_unparseFull (ue)));
2620 else if (qual_isAllocQual (qel)) /* out, partial, reldef, special, etc. */
2622 ctype realType = ctype_realType (ue->utype);
2623 sstate defstate = sstate_fromQual (qel);
2625 if (ctype_isFunction (realType))
2627 realType = ctype_realType (ctype_getReturnType (realType));
2630 if (qual_isRelDef (qel))
2632 ; /* okay anywhere */
2636 if (!ctype_isAP (realType)
2637 && !ctype_isSU (realType)
2638 && !ctype_isUnknown (realType)
2639 && !ctype_isAbstract (ue->utype))
2642 (FLG_ANNOTATIONERROR,
2643 message ("Qualifier %s used on non-pointer or struct: %q",
2644 qual_unparse (qel), uentry_unparse (ue)),
2645 uentry_whereLast (ue));
2649 uentry_setDefState (ue, defstate);
2651 if (sRef_isStateSpecial (ue->sref)
2652 && alkind_isImplicit (sRef_getAliasKind (ue->sref)))
2654 sRef_setAliasKind (ue->sref, AK_ERROR, fileloc_undefined);
2657 else if (qual_isYield (qel))
2659 if (uentry_isVariable (ue))
2661 ue->info->var->kind = VKYIELDPARAM;
2666 (FLG_ANNOTATIONERROR,
2667 message ("Qualifier %s used on non-iterator parameter: %q",
2668 qual_unparse (qel), uentry_unparse (ue)),
2669 uentry_whereLast (ue));
2672 else if (qual_isExQual (qel))
2674 exkind ek = exkind_fromQual (qel);
2675 ctype ut = uentry_getType (ue);
2677 DPRINTF (("Reflect ex qual: %s / %s",
2678 uentry_unparse (ue), exkind_unparse (ek)));
2680 if (ctype_isFunction (ut))
2682 ut = ctype_getReturnType (ut);
2685 if (!(ctype_isVisiblySharable (ut))
2686 && !(ctype_isArray (ut)) /* can apply to arrays also! */
2687 && !(ctype_isStruct (ctype_realType (ut)))) /* applies to structure fields! */
2689 if (!qual_isImplied (qel))
2691 if (ctype_isImmutableAbstract (ut)) {
2693 (FLG_REDUNDANTSHAREQUAL,
2694 message ("Qualifier %s used on unsharable storage type %t: %q",
2695 exkind_unparse (ek), ut, uentry_getName (ue)),
2696 uentry_whereLast (ue));
2699 (FLG_MISPLACEDSHAREQUAL,
2700 message ("Qualifier %s used on unsharable storage type %t: %q",
2701 exkind_unparse (ek), ut, uentry_getName (ue)),
2702 uentry_whereLast (ue));
2708 alkind ak = sRef_getAliasKind (ue->sref);
2710 sRef_setExKind (ue->sref, ek, uentry_whereDeclared (ue));
2711 DPRINTF (("Set exkind: %s", sRef_unparseFull (ue->sref)));
2713 if (alkind_isUnknown (ak) || alkind_isImplicit (ak) || alkind_isStatic (ak))
2715 if (!alkind_isTemp (ak))
2717 DPRINTF (("imp dep: %s", uentry_unparseFull (ue)));
2718 uentry_setAliasKind (ue, AK_IMPDEPENDENT);
2721 else if (alkind_isDependent (ak) || alkind_isTemp (ak)
2722 || alkind_isOwned (ak))
2730 message ("Exposure qualifier %s used on %s storage (should "
2731 "be dependent): %q",
2733 alkind_unparse (ak),
2734 uentry_unparse (ue)));
2738 else if (qual_isGlobCheck (qel))
2740 if (uentry_isVariable (ue))
2742 chkind ch = chkind_fromQual (qel);
2744 if (ue->info->var->checked != CH_UNKNOWN)
2746 if (ch == ue->info->var->checked)
2748 llerror (FLG_SYNTAX,
2749 message ("Redundant %s qualifier on %q",
2751 uentry_getName (ue)));
2755 llerror (FLG_SYNTAX,
2757 ("Contradictory %s and %s qualifiers on %q",
2759 checkedName (ue->info->var->checked),
2760 uentry_getName (ue)));
2764 ue->info->var->checked = ch;
2770 message ("Qualifier %s used with non-variable",
2771 qual_unparse (qel)));
2774 else if (qual_isReturned (qel))
2776 if (uentry_isVariable (ue))
2778 ue->info->var->kind = VKRETPARAM;
2782 llerror (FLG_SYNTAX, message ("Qualifier %s used with non-variable",
2783 qual_unparse (qel)));
2788 uentry_reflectOtherQualifier (ue, qel);
2791 sRef_storeState (ue->sref);
2792 } end_qualList_elements;
2798 uentry_isOnly (uentry ue)
2800 return (!uentry_isUndefined (ue)
2801 && uentry_isVariable (ue)
2802 && alkind_isOnly (sRef_getOrigAliasKind (ue->sref)));
2806 uentry_setAliasKind (/*@notnull@*/ uentry ue, alkind ak)
2808 sRef_setAliasKind (ue->sref, ak, uentry_whereDeclared (ue));
2809 sRef_setOrigAliasKind (ue->sref, ak);
2813 uentry_setNullState (/*@notnull@*/ uentry ue, nstate ns)
2815 if (uentry_isVariable (ue))
2817 ue->info->var->nullstate = ns;
2820 sRef_setNullState (ue->sref, ns, uentry_whereDeclared (ue));
2824 uentry_isUnique (uentry ue)
2826 return (!uentry_isUndefined (ue)
2827 && uentry_isVariable (ue)
2828 && alkind_isUnique (sRef_getOrigAliasKind (ue->sref)));
2832 uentry_isFileStatic (uentry ue)
2834 return (uentry_isStatic (ue)
2835 && (!uentry_isVariable (ue)
2836 || sRef_isFileStatic (uentry_getSref (ue))));
2840 uentry_isExported (uentry ue)
2842 if (uentry_isValid (ue))
2844 if (uentry_isVariable (ue))
2846 return (sRef_isRealGlobal (uentry_getSref (ue)));
2850 return !uentry_isStatic (ue);
2858 uentry_isNonLocal (uentry ue)
2860 return (uentry_isValid (ue) && uentry_isVariable (ue)
2861 && (sRef_isFileOrGlobalScope (ue->sref) || uentry_isStatic (ue)));
2865 uentry_isGlobalVariable (uentry ue)
2867 return (uentry_isValid (ue) && uentry_isVariable (ue)
2868 && sRef_isFileOrGlobalScope (ue->sref));
2872 uentry_isVisibleExternally (uentry ue)
2874 return (uentry_isValid (ue)
2875 && ((uentry_isVariable (ue) && sRef_isRealGlobal (ue->sref))
2876 || (!uentry_isStatic (ue)
2877 && (uentry_isFunction (ue)
2878 || uentry_isIter (ue)
2879 || uentry_isEndIter (ue)
2880 || uentry_isConstant (ue)
2881 || uentry_isDatatype (ue)
2882 || uentry_isAnyTag (ue)))));
2886 uentry_isPrintfLike (uentry ue)
2888 return (uentry_isFunction (ue)
2889 && (ue->info->fcn->specialCode == SPC_PRINTFLIKE));
2893 uentry_isScanfLike (uentry ue)
2895 return (uentry_isFunction (ue)
2896 && (ue->info->fcn->specialCode == SPC_SCANFLIKE));
2900 uentry_isMessageLike (uentry ue)
2902 return (uentry_isFunction (ue)
2903 && (ue->info->fcn->specialCode == SPC_MESSAGELIKE));
2906 static void checkSpecialFunction (/*@notnull@*/ uentry ue)
2908 uentryList args = uentry_getParams (ue);
2910 if (!uentryList_isMissingParams (args))
2912 uentry last = uentry_undefined;
2914 uentryList_elements (args, current)
2916 if (uentry_isElipsisMarker (current))
2918 if (uentry_isUndefined (last))
2922 message ("Function %q is marked %s, but has no format "
2923 "string argument before elipsis",
2924 uentry_getName (ue),
2925 specCode_unparse (ue->info->fcn->specialCode)),
2926 uentry_whereLast (ue));
2927 ue->info->fcn->specialCode = SPC_NONE;
2931 ctype rt = ctype_realType (uentry_getType (last));
2933 if (!ctype_match (rt, ctype_string))
2937 /* wchar_t * is okay too */
2938 if (ctype_isAP (rt))
2940 ctype base = ctype_baseArrayPtr (rt);
2942 if (ctype_isArbitraryIntegral (base))
2952 message ("Function %q is marked %s, but the argument "
2953 "before the elipsis has type %s (should be char *)",
2954 uentry_getName (ue),
2955 specCode_unparse (ue->info->fcn->specialCode),
2956 ctype_unparse (uentry_getType (last))),
2957 uentry_whereLast (ue));
2959 ue->info->fcn->specialCode = SPC_NONE;
2966 } end_uentryList_elements ;
2970 message ("Function %q is marked %s, but has no elipsis parameter",
2971 uentry_getName (ue),
2972 specCode_unparse (ue->info->fcn->specialCode)),
2973 uentry_whereLast (ue));
2975 ue->info->fcn->specialCode = SPC_NONE;
2980 uentry_setPrintfLike (uentry ue)
2982 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2984 uentry_makeVarFunction (ue);
2987 llassertfatal (uentry_isFunction (ue));
2988 ue->info->fcn->specialCode = SPC_PRINTFLIKE;
2989 checkSpecialFunction (ue);
2993 uentry_setScanfLike (uentry ue)
2995 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
2997 uentry_makeVarFunction (ue);
3000 llassertfatal (uentry_isFunction (ue));
3001 ue->info->fcn->specialCode = SPC_SCANFLIKE;
3002 checkSpecialFunction (ue);
3006 uentry_setMessageLike (uentry ue)
3008 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
3010 uentry_makeVarFunction (ue);
3013 llassertfatal (uentry_isFunction (ue));
3014 ue->info->fcn->specialCode = SPC_MESSAGELIKE;
3015 checkSpecialFunction (ue);
3019 uentry_isSpecialFunction (uentry ue)
3021 return (uentry_isFunction (ue)
3022 && (ue->info->fcn->specialCode != SPC_NONE));
3025 /*@notnull@*/ uentry uentry_makeParam (idDecl t, int i)
3027 ctype ct = idDecl_getCtype (t);
3029 sRef pref = sRef_makeParam (i, ct);
3030 uentry ue = uentry_makeVariableSrefParam (idDecl_observeId (t), ct, pref);
3032 uentry_reflectQualifiers (ue, idDecl_getQuals (t));
3033 uentry_implicitParamAnnots (ue);
3035 /* Parameter type [][] or [x][] is invalid */
3037 while (ctype_isFixedArray (base)) {
3038 base = ctype_baseArrayPtr (base);
3041 if (ctype_isIncompleteArray (base)) {
3042 base = ctype_baseArrayPtr (base);
3044 if (ctype_isArray (base)) {
3045 if (!uentry_hasName (ue)) {
3046 (void) optgenerror (FLG_INCOMPLETETYPE,
3047 message ("Unnamed function parameter %d is incomplete type (inner array must have bounds): %s",
3049 ctype_unparse (ct)),
3050 uentry_whereLast (ue));
3052 (void) optgenerror (FLG_INCOMPLETETYPE,
3053 message ("Function parameter %q is incomplete type (inner array must have bounds): %s",
3054 uentry_getName (ue),
3055 ctype_unparse (ct)),
3056 uentry_whereLast (ue));
3061 DPRINTF (("Param: %s", uentry_unparseFull (ue)));
3065 /*@only@*/ /*@notnull@*/ uentry uentry_makeIdVariable (idDecl t)
3067 ctype ct = idDecl_getCtype (t);
3069 if (ctype_isFunction (ct))
3071 return (uentry_makeIdFunction (t));
3075 fileloc loc = setLocation ();
3076 uentry ue = uentry_makeVariable (idDecl_observeId (t), ct, loc, FALSE);
3078 uentry_reflectQualifiers (ue, idDecl_getQuals (t));
3080 if (!uentry_isExtern (ue))
3082 uentry_setDefined (ue, loc);
3090 /*@notnull@*/ uentry uentry_makeVariableParam (cstring n, ctype t)
3092 return (uentry_makeVariableParamAux (n, t, sRef_makeType (t), SS_DEFINED));
3100 /*@only@*/ /*@notnull@*/
3101 uentry uentry_makeConstantAux (cstring n, ctype t,
3102 /*@keep@*/ fileloc f, bool priv,
3103 /*@only@*/ multiVal m)
3105 uentry e = uentry_alloc ();
3108 e->uname = cstring_copy (n);
3110 e->storageclass = SCNONE;
3112 e->warn = warnClause_undefined; /*@i32 warnings for constants? */
3114 e->sref = sRef_makeConst (t);
3119 e->uses = filelocList_new ();
3120 e->isPrivate = priv;
3121 e->hasNameError = FALSE;
3123 e->info = (uinfo) dmalloc (sizeof (*e->info));
3124 e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
3125 e->info->uconst->val = m;
3126 e->info->uconst->access = typeIdSet_undefined;
3128 uentry_setSpecDef (e, f);
3130 if (multiVal_isInt (m) && (multiVal_forceInt (m) == 0))
3132 sRef_setDefNull (e->sref, uentry_whereDeclared (e));
3138 /*@notnull@*/ uentry uentry_makeConstant (cstring n, ctype t, fileloc f)
3140 return (uentry_makeConstantAux (n, t, f, FALSE, multiVal_unknown ()));
3143 /*@notnull@*/ uentry uentry_makeIdConstant (idDecl t)
3145 uentry ue = uentry_makeConstant (idDecl_observeId (t),
3146 idDecl_getCtype (t),
3149 llassert (fileloc_isUndefined (ue->whereDeclared));
3150 ue->whereDeclared = setLocation ();
3152 uentry_reflectQualifiers (ue, idDecl_getQuals (t));
3161 void uentry_setDefState (uentry ue, sstate defstate)
3163 if (uentry_isValid (ue))
3165 sRef_setDefState (ue->sref, defstate, fileloc_undefined);
3167 if (uentry_isVariable (ue))
3169 ue->info->var->defstate = defstate; /* evs 2000-05-17: fixed bug, was SS_DEFINED! */
3174 bool uentry_isCheckedUnknown (uentry ue)
3176 return (uentry_isVar (ue)
3177 && (ue->info->var->checked == CH_UNKNOWN));
3180 bool uentry_isCheckMod (uentry ue)
3182 return (uentry_isVar (ue)
3183 && (ue->info->var->checked == CH_CHECKMOD));
3186 bool uentry_isUnchecked (uentry ue)
3188 return (uentry_isVar (ue)
3189 && (ue->info->var->checked == CH_UNCHECKED));
3192 bool uentry_isChecked (uentry ue)
3194 return (uentry_isVar (ue)
3195 && (ue->info->var->checked == CH_CHECKED));
3198 bool uentry_isCheckedModify (uentry ue)
3200 return (uentry_isVar (ue)
3201 && (ue->info->var->checked == CH_CHECKED
3202 || ue->info->var->checked == CH_CHECKMOD
3203 || ue->info->var->checked == CH_CHECKEDSTRICT));
3206 bool uentry_isCheckedStrict (uentry ue)
3208 return (uentry_isVar (ue)
3209 && (ue->info->var->checked == CH_CHECKEDSTRICT));
3212 void uentry_setUnchecked (uentry ue)
3214 llassert (uentry_isVar (ue));
3216 ue->info->var->checked = CH_UNCHECKED;
3219 void uentry_setChecked (uentry ue)
3221 llassert (uentry_isVar (ue));
3223 ue->info->var->checked = CH_CHECKED;
3226 void uentry_setCheckMod (uentry ue)
3228 llassert (uentry_isVar (ue));
3230 ue->info->var->checked = CH_CHECKMOD;
3233 void uentry_setCheckedStrict (uentry ue)
3235 llassert (uentry_isVar (ue));
3237 ue->info->var->checked = CH_CHECKEDSTRICT;
3240 static /*@only@*/ /*@notnull@*/
3241 uentry uentry_makeVariableAux (cstring n, ctype t,
3243 /*@exposed@*/ sRef s,
3244 bool priv, vkind kind)
3246 uentry e = uentry_alloc ();
3249 DPRINTF (("Make variable: %s %s %s", n, ctype_unparse (t), sRef_unparse (s)));
3252 e->uname = cstring_copy (n);
3255 e->storageclass = SCNONE;
3257 e->warn = warnClause_undefined; /*@i32 warnings for variable @*/
3264 e->uses = filelocList_new ();
3265 e->isPrivate = priv;
3266 e->hasNameError = FALSE;
3268 e->info = (uinfo) dmalloc (sizeof (*e->info));
3269 e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
3270 e->info->var->kind = kind;
3272 e->info->var->checked = CH_UNKNOWN;
3274 DPRINTF (("Here we are: %s", sRef_unparseFull (e->sref)));
3275 uentry_setSpecDef (e, f);
3276 DPRINTF (("Here we are: %s", sRef_unparseFull (e->sref)));
3278 if (ctype_isFunction (rt))
3280 rt = ctype_getReturnType (rt);
3283 if (ctype_isUA (rt))
3285 DPRINTF (("Here we are: %s", sRef_unparseFull (e->sref)));
3286 sRef_setStateFromType (e->sref, rt);
3289 DPRINTF (("Here we are: %s", sRef_unparseFull (e->sref)));
3290 e->info->var->defstate = sRef_getDefState (e->sref);
3291 e->info->var->nullstate = sRef_getNullState (e->sref);
3293 /* start modifications */
3294 /* This function sets the uentry for a pointer or array variable declaration,
3295 it allocates memory and sets the fields. We check if the type of the variable
3296 is a pointer or array and allocate a `bbufinfo' struct accordingly */
3298 if( ctype_isArray (t) || ctype_isPointer(t)) {
3299 /*@i222@*/e->info->var->bufinfo = dmalloc( sizeof(*e->info->var->bufinfo) );
3300 e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED;
3301 /*@access sRef@*/ /*i@222*/
3302 /* It probably isn't necessary to violate the abstraction here
3305 s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
3308 e->info->var->bufinfo = NULL;
3310 /* end modification */
3316 uentry_isYield (uentry ue)
3318 return (uentry_isVariable (ue)
3319 && (ue->info->var->kind == VKYIELDPARAM
3320 || ue->info->var->kind == VKREFYIELDPARAM));
3324 uentry_isRefsField (uentry ue)
3326 return (uentry_isVariable (ue) && sRef_isRefsField (ue->sref));
3329 /*@only@*/ /*@notnull@*/
3330 uentry uentry_makeVariable (cstring n, ctype t, fileloc f, bool isPriv)
3332 return (uentry_makeVariableAux (n, t, f, sRef_makeType (t), isPriv,
3333 fileloc_isSpec (f) ? VKSPEC : VKNORMAL));
3340 void uentry_makeVarFunction (uentry ue)
3347 llassert (uentry_isValid (ue));
3348 llassert (!sRef_modInFunction ());
3350 ak = sRef_getOrigAliasKind (ue->sref);
3351 ek = sRef_getOrigExKind (ue->sref);
3353 oldInfo = ue->info->var;
3355 llassert (ctype_isUnknown (ue->utype) || ctype_isFunction (ue->utype));
3358 ** expanded macro is marked used (until I write a pre-processor)
3361 ue->used |= (oldInfo->kind == VKEXPMACRO);
3364 ue->info->fcn = (ufinfo) dmalloc (sizeof (*ue->info->fcn));
3365 ue->info->fcn->exitCode = XK_UNKNOWN;
3366 ue->info->fcn->nullPred = qual_createUnknown ();
3367 ue->info->fcn->specialCode = SPC_NONE;
3368 ue->info->fcn->access = typeIdSet_undefined;
3369 ue->info->fcn->hasGlobs = FALSE;
3370 ue->info->fcn->globs = globSet_undefined;
3371 ue->info->fcn->hasMods = FALSE;
3372 ue->info->fcn->mods = sRefSet_undefined;
3373 ue->info->fcn->specclauses = NULL;
3374 ue->info->fcn->defparams = uentryList_undefined;
3377 ue->info->fcn->preconditions = functionConstraint_undefined;
3381 ue->info->fcn->postconditions = functionConstraint_undefined;
3385 if (ctype_isFunction (ue->utype))
3387 ue->sref = sRef_makeType (ctype_getReturnType (ue->utype));
3391 ue->sref = sRef_makeType (ctype_unknown);
3394 if (sRef_isRefCounted (ue->sref))
3400 if (alkind_isUnknown (ak))
3402 if (exkind_isKnown (ek))
3404 DPRINTF (("imp dep: %s", uentry_unparseFull (ue)));
3405 ak = AK_IMPDEPENDENT;
3409 if (context_getFlag (FLG_RETIMPONLY))
3411 if (ctype_isFunction (ue->utype)
3412 && ctype_isVisiblySharable
3413 (ctype_realType (ctype_getReturnType (ue->utype))))
3415 if (uentryList_hasReturned (uentry_getParams (ue)))
3421 if (ctype_isImmutableAbstract (ctype_getReturnType (ue->utype)))
3436 loc = ue->whereDeclared;
3438 sRef_setAliasKind (ue->sref, ak, loc);
3439 sRef_setNullState (ue->sref, oldInfo->nullstate, loc);
3440 sRef_setDefState (ue->sref, oldInfo->defstate, loc);
3441 sRef_setExKind (ue->sref, ek, loc);
3443 if (oldInfo->kind == VKEXPMACRO)
3446 ue->whereDeclared = fileloc_undefined;
3450 fileloc_free (ue->whereDefined);
3451 ue->whereDefined = fileloc_undefined;
3454 uvinfo_free (oldInfo);
3458 uentry_setGlobals (uentry ue, /*@owned@*/ globSet globs)
3460 llassert (uentry_isValid (ue));
3462 if (uentry_isIter (ue))
3464 llassert (globSet_isUndefined (ue->info->iter->globs));
3465 ue->info->iter->globs = globs;
3469 if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue)))
3471 uentry_makeVarFunction (ue);
3474 llassert (uentry_isFunction (ue));
3475 llassert (!ue->info->fcn->hasGlobs
3476 && globSet_isUndefined (ue->info->fcn->globs));
3478 ue->info->fcn->hasGlobs = TRUE;
3479 globSet_markImmutable (globs);
3480 /*@-mustfree@*/ ue->info->fcn->globs = globs;
3485 if (globSet_hasStatic (globs))
3487 context_recordFileGlobals (globs);
3491 if (context_getFlag (FLG_GLOBALSIMPMODIFIESNOTHING))
3493 ue->info->fcn->hasMods = TRUE;
3497 void uentry_addAccessType (uentry ue, typeId tid)
3499 if (uentry_isFunction (ue))
3501 ue->info->fcn->access = typeIdSet_insert (ue->info->fcn->access, tid);
3503 else if (uentry_isEitherConstant (ue))
3505 ue->info->uconst->access = typeIdSet_insert (ue->info->uconst->access, tid);
3507 else if (uentry_isIter (ue))
3509 ue->info->iter->access = typeIdSet_insert (ue->info->iter->access, tid);
3511 else if (uentry_isEndIter (ue))
3513 ue->info->enditer->access = typeIdSet_insert (ue->info->enditer->access, tid);
3517 llbug (message ("no access for: %q", uentry_unparse (ue)));
3521 /*@only@*/ /*@notnull@*/ uentry
3522 uentry_makeFunction (cstring n, ctype t,
3524 /*@only@*/ globSet globs, /*@only@*/ sRefSet mods,
3525 /*@only@*/ warnClause warn,
3528 llassert (warnClause_isUndefined (warn)); /*@i325 remove parameter! */
3529 return (uentry_makeFunctionAux (n, t,
3530 ((typeId_isInvalid (access)) ? typeIdSet_emptySet ()
3531 : typeIdSet_single (access)),
3538 /*@notnull@*/ uentry
3539 uentry_makePrivFunction2 (cstring n, ctype t,
3541 globSet globs, sRefSet mods,
3544 return (uentry_makeFunctionAux (n, t, access, globs, mods, warnClause_undefined,
3549 /*@notnull@*/ uentry
3550 uentry_makeSpecFunction (cstring n, ctype t,
3552 /*@only@*/ globSet globs,
3553 /*@only@*/ sRefSet mods,
3556 uentry ue = uentry_makeFunctionAux (n, t, access,
3557 globs, mods, warnClause_undefined,
3560 uentry_setHasGlobs (ue);
3561 uentry_setHasMods (ue);
3563 reflectImplicitFunctionQualifiers (ue, TRUE);
3568 uentry uentry_makeExpandedMacro (cstring s, fileloc f)
3570 uentry ue = uentry_makeVariableAux (s, ctype_unknown, fileloc_undefined,
3571 sRef_undefined, FALSE, VKEXPMACRO);
3573 uentry_setDefined (ue, f);
3577 /*@notnull@*/ /*@notnull@*/ uentry
3578 uentry_makeForwardFunction (cstring n, typeId access, fileloc f)
3580 uentry ue = uentry_makeFunctionAux (n, ctype_unknown,
3581 typeIdSet_singleOpt (access),
3582 globSet_undefined, sRefSet_undefined,
3583 warnClause_undefined,
3587 ue->whereDeclared = fileloc_update (ue->whereDeclared, f);
3591 bool uentry_isForward (uentry e)
3593 if (uentry_isValid (e))
3595 ctype ct = uentry_getType (e);
3597 return (ctype_isUnknown (ct)
3598 || (ctype_isFunction (ct)
3599 && ctype_isUnknown (ctype_getReturnType (ct))));
3606 /*@notnull@*/ uentry
3607 uentry_makeTypeListFunction (cstring n, typeIdSet access, fileloc f)
3609 return (uentry_makeFunctionAux (n, ctype_unknown, access,
3610 globSet_undefined, sRefSet_undefined, warnClause_undefined,
3614 /*@notnull@*/ uentry
3615 uentry_makeUnspecFunction (cstring n, ctype t,
3619 uentry ue = uentry_makeFunctionAux (n, t, access, globSet_undefined,
3620 sRefSet_undefined, warnClause_undefined,
3623 reflectImplicitFunctionQualifiers (ue, TRUE);
3632 /* is exported for use by usymtab_interface */
3634 /*@notnull@*/ uentry
3635 uentry_makeDatatypeAux (cstring n, ctype t, ynm mut, ynm abstract,
3636 fileloc f, bool priv)
3638 uentry e = uentry_alloc ();
3640 DPRINTF (("Make datatype: %s / %s",
3641 n, ctype_unparse (t)));
3643 /* e->shallowCopy = FALSE; */
3644 e->ukind = KDATATYPE;
3645 e->uname = cstring_copy (n);
3647 e->storageclass = SCNONE;
3648 e->sref = sRef_makeUnknown ();
3652 sRef_setStateFromType (e->sref, t);
3655 uentry_setSpecDef (e, f);
3657 e->warn = warnClause_undefined; /*@i634@*/
3658 e->uses = filelocList_new ();
3659 e->isPrivate = priv;
3660 e->hasNameError = FALSE;
3665 e->info = (uinfo) dmalloc (sizeof (*e->info));
3666 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3667 e->info->datatype->abs = abstract;
3668 e->info->datatype->mut = mut;
3669 e->info->datatype->type = ctype_undefined;
3671 if (uentry_isDeclared (e))
3673 uentry_setDefined (e, f);
3676 if (ynm_isOn (abstract) && !(uentry_isCodeDefined (e)))
3678 sRef_setNullState (e->sref, NS_ABSNULL, uentry_whereDeclared (e));
3684 /*@notnull@*/ uentry
3685 uentry_makeDatatype (cstring n, ctype t, ynm mut, ynm abstract, fileloc f)
3687 return (uentry_makeDatatypeAux (n, t, mut, abstract, f, FALSE));
3690 /*@notnull@*/ uentry uentry_makeBoolDatatype (ynm abstract)
3692 uentry ret = uentry_makeDatatypeAux (context_getBoolName (),
3693 ctype_bool, NO, abstract,
3694 fileloc_getBuiltin (),
3697 ret->info->datatype->type = ctype_bool;
3705 static /*@only@*/ /*@notnull@*/ uentry
3706 uentry_makeIterAux (cstring n, typeIdSet access, ctype ct,
3707 /*@only@*/ fileloc f)
3709 uentry e = uentry_alloc ();
3712 e->uname = cstring_copy (n);
3714 e->sref = sRef_makeUnknown ();
3715 e->storageclass = SCNONE;
3719 uentry_setSpecDef (e, f);
3721 e->warn = warnClause_undefined; /*@i452@*/
3722 e->uses = filelocList_new ();
3723 e->isPrivate = FALSE;
3724 e->hasNameError = FALSE;
3726 e->info = (uinfo) dmalloc (sizeof (*e->info));
3727 e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
3728 e->info->iter->access = access;
3729 e->info->iter->mods = sRefSet_undefined;
3730 e->info->iter->globs = globSet_undefined;
3732 uentry_checkIterArgs (e);
3736 /*@notnull@*/ uentry uentry_makeIter (cstring n, ctype ct, fileloc f)
3738 return (uentry_makeIterAux (n, context_fileAccessTypes (), ct, f));
3741 static /*@notnull@*/ uentry
3742 uentry_makeEndIterAux (cstring n, typeIdSet access, /*@only@*/ fileloc f)
3744 uentry e = uentry_alloc ();
3746 /* e->shallowCopy = FALSE; */
3747 e->ukind = KENDITER;
3748 e->storageclass = SCNONE;
3749 e->uname = message ("end_%s", n);
3750 e->utype = ctype_unknown;
3751 e->sref = sRef_makeUnknown ();
3753 uentry_setSpecDef (e, f);
3758 e->uses = filelocList_new ();
3759 e->isPrivate = FALSE;
3760 e->hasNameError = FALSE;
3762 e->info = (uinfo) dmalloc (sizeof (*e->info));
3763 e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
3765 e->info->enditer->access = access;
3767 e->warn = warnClause_undefined; /*@i452@*/
3771 /*@notnull@*/ /*@only@*/ uentry uentry_makeEndIter (cstring n, fileloc f)
3773 return (uentry_makeEndIterAux (n, context_fileAccessTypes (), f));
3780 static /*@only@*/ /*@notnull@*/ uentry
3781 uentry_makeTagAux (cstring n, ctype t,
3782 /*@only@*/ fileloc fl,
3783 bool priv, ekind kind)
3785 uentry e = uentry_alloc ();
3787 if (kind != KSTRUCTTAG && kind != KUNIONTAG && kind != KENUMTAG)
3789 llbuglit ("uentry_makeTagAux: not a tag type");
3793 /* e->shallowCopy = FALSE; */
3794 e->uname = cstring_copy (n);
3797 e->sref = sRef_makeUnknown ();
3798 e->storageclass = SCNONE;
3800 uentry_setSpecDef (e, fl);
3805 e->uses = filelocList_new ();
3806 e->isPrivate = priv;
3807 e->hasNameError = FALSE;
3809 e->info = (uinfo) dmalloc (sizeof (*e->info));
3810 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
3811 e->info->datatype->abs = NO;
3812 e->info->datatype->mut = (kind == KENUMTAG) ? NO : MAYBE;
3813 e->info->datatype->type = t;
3814 e->warn = warnClause_undefined; /*@i452@*/
3816 if (uentry_isDeclared (e))
3818 uentry_setDefined (e, fl);
3824 uentry uentry_makeStructTagLoc (cstring n, ctype t)
3826 cstring sname = makeStruct (n);
3827 uentry ret = uentry_makeTagAux (sname, t, setLocation (), FALSE, KSTRUCTTAG);
3829 cstring_free (sname);
3834 uentry_makeStructTag (cstring n, ctype t, fileloc loc)
3836 cstring sname = makeStruct (n);
3837 uentry ret = uentry_makeTagAux (sname, t, loc, FALSE, KSTRUCTTAG);
3839 cstring_free (sname);
3844 uentry_makeUnionTag (cstring n, ctype t, fileloc loc)
3846 cstring uname = makeUnion (n);
3847 uentry ret = uentry_makeTagAux (uname, t, loc, FALSE, KUNIONTAG);
3849 cstring_free (uname);
3855 uentry_makeEnumTag (cstring n, ctype t, fileloc loc)
3857 cstring ename = makeEnum (n);
3858 uentry ret = uentry_makeTagAux (ename, t, loc, FALSE, KENUMTAG);
3860 cstring_free (ename);
3866 uentry_makeUnionTagLoc (cstring n, ctype t)
3868 cstring uname = makeUnion (n);
3869 uentry ret = uentry_makeTagAux (uname, t, setLocation (), FALSE, KUNIONTAG);
3871 cstring_free (uname);
3876 uentry_makeEnumTagLoc (cstring n, ctype t)
3878 cstring ename = makeEnum (n);
3879 uentry ret = uentry_makeTagAux (ename, t, setLocation (), FALSE, KENUMTAG);
3881 cstring_free (ename);
3886 uentry_isStructTag (uentry ue)
3888 return (uentry_isValid (ue) && ue->ukind == KSTRUCTTAG);
3892 uentry_isUnionTag (uentry ue)
3894 return (uentry_isValid (ue) && ue->ukind == KUNIONTAG);
3898 uentry_isEnumTag (uentry ue)
3900 return (uentry_isValid (ue) && ue->ukind == KENUMTAG);
3904 uentry_isAnyTag (uentry ue)
3906 return (uentry_isStructTag (ue)
3907 || uentry_isUnionTag (ue)
3908 || uentry_isEnumTag (ue));
3911 static /*@unchecked@*/ /*@only@*/ uentry emarker = NULL;
3913 extern void uentry_destroyMod (void)
3914 /*@globals killed emarker@*/ /*@modifies emarker@*/
3916 static bool wasDestroyed = FALSE;
3918 llassert (!wasDestroyed);
3920 if (emarker != NULL)
3922 uentry_reallyFree (emarker);
3925 wasDestroyed = TRUE;
3929 uentry_makeElipsisMarker (void)
3931 if (emarker == NULL)
3933 emarker = uentry_alloc ();
3935 emarker->ukind = KELIPSMARKER;
3936 emarker->uname = cstring_makeLiteral ("...");
3937 emarker->utype = ctype_elipsMarker;
3938 emarker->sref = sRef_undefined;
3939 emarker->storageclass = SCNONE;
3940 emarker->used = FALSE;
3941 emarker->lset = FALSE;
3942 emarker->info = NULL;
3944 uentry_setSpecDef (emarker, fileloc_undefined);
3945 emarker->uses = filelocList_new ();
3946 emarker->isPrivate = FALSE;
3947 emarker->hasNameError = FALSE;
3950 /*@ignore@*/ return (emarker); /*@end@*/
3958 uentry_equiv (uentry p1, uentry p2)
3960 if (uentry_compare (p1, p2) != 0)
3971 uentry_xcomparealpha (uentry *p1, uentry *p2)
3975 if ((res = uentry_compare (*p1, *p2)) == 0) {
3976 if ((*p1 != NULL) && (*p2 != NULL)) {
3977 res = cstring_compare ((*p1)->uname,
3986 uentry_xcompareuses (uentry *p1, uentry *p2)
3991 if (uentry_isValid (u1))
3993 if (uentry_isValid (u2))
3995 return (-1 * int_compare (filelocList_size (u1->uses),
3996 filelocList_size (u2->uses)));
4005 if (uentry_isValid (u2))
4017 uentry_compareStrict (uentry v1, uentry v2)
4019 COMPARERETURN (uentry_compare (v1, v2));
4021 if (v1 != v2 && uentry_isValid (v1) && uentry_isValid (v2))
4023 COMPARERETURN (fileloc_compare (v1->whereDeclared, v2->whereDeclared));
4024 COMPARERETURN (fileloc_compare (v1->whereDefined, v2->whereDefined));
4025 COMPARERETURN (fileloc_compare (v1->whereSpecified, v2->whereSpecified));
4032 uentry_compare (uentry u1, uentry u2)
4034 if (u1 == u2) return 0;
4036 if (uentry_isInvalid (u1)) return -1;
4037 if (uentry_isInvalid (u2)) return 1;
4039 INTCOMPARERETURN (u1->ukind, u2->ukind);
4040 COMPARERETURN (ctype_compare (u1->utype, u2->utype));
4041 COMPARERETURN (bool_compare (uentry_isPriv (u1), uentry_isPriv (u2)));
4042 COMPARERETURN (sRef_compare (u1->sref, u2->sref));
4048 /* bug detected by lclint:
4049 ** uentry.c:753,14: Return value type bool does not match declared type int: TRUE
4054 return (multiVal_compare (u1->info->uconst->val,
4055 u2->info->uconst->val));
4059 return (ctype_compare (u1->info->datatype->type, u2->info->datatype->type));
4061 COMPARERETURN (typeIdSet_compare (uentry_accessType (u1),
4062 uentry_accessType (u2)));
4063 return (uentryList_compareParams (uentry_getParams (u1),
4064 uentry_getParams (u2)));
4066 return (typeIdSet_compare (uentry_accessType (u1),
4067 uentry_accessType (u2)));
4070 ** Functions are never equivalent
4073 if ((int) u1 < (int) u2)
4083 COMPARERETURN (generic_compare (u1->info->var->kind, u2->info->var->kind));
4084 COMPARERETURN (generic_compare (sRef_getOrigAliasKind (u1->sref),
4085 sRef_getOrigAliasKind (u2->sref)));
4086 COMPARERETURN (generic_compare (sRef_getOrigExKind (u1->sref),
4087 sRef_getOrigExKind (u2->sref)));
4088 COMPARERETURN (generic_compare (u1->info->var->checked,
4089 u2->info->var->checked));
4090 COMPARERETURN (generic_compare (u1->info->var->defstate,
4091 u2->info->var->defstate));
4092 return (generic_compare (u1->info->var->nullstate,
4093 u2->info->var->nullstate));
4095 COMPARERETURN (ctype_compare (u1->info->datatype->type,
4096 u2->info->datatype->type));
4097 COMPARERETURN (ynm_compare (u1->info->datatype->mut,
4098 u2->info->datatype->mut));
4099 return (ynm_compare (u1->info->datatype->abs, u2->info->datatype->abs));
4108 ** all entries are: <type>[@<info>]*#<name>
4110 ** info depends on kind:
4114 advanceField (char **s)
4116 reader_checkChar (s, '@');
4120 advanceName (char **s)
4122 reader_checkChar (s, '#');
4126 vkind_fromInt (int i)
4128 if /*@+enumint@*/ (i < VKFIRST || i > VKLAST) /*@=enumint@*/
4130 llbuglit ("vkind_fromInt: out of range");
4137 uentry_makeConstantBase (/*@only@*/ cstring name, ctype ct,
4138 typeIdSet access, nstate nullstate,
4139 /*@keep@*/ fileloc loc, /*@only@*/ multiVal m)
4141 uentry e = uentry_alloc ();
4146 e->sref = sRef_makeConst (ct);
4148 sRef_setNullState (e->sref, nullstate, loc);
4149 e->storageclass = SCNONE;
4151 if (fileloc_isSpec (loc))
4153 e->whereSpecified = loc;
4154 e->whereDeclared = fileloc_undefined;
4158 e->whereSpecified = fileloc_undefined;
4159 e->whereDeclared = loc;
4162 e->whereDefined = fileloc_undefined;
4163 e->uses = filelocList_new ();
4164 e->isPrivate = FALSE;
4165 e->hasNameError = FALSE;
4170 e->warn = warnClause_undefined; /*@i452@*/
4172 e->info = (uinfo) dmalloc (sizeof (*e->info));
4173 e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
4174 e->info->uconst->val = m;
4175 e->info->uconst->access = access;
4177 sRef_storeState (e->sref);
4182 static /*@only@*/ uentry
4183 uentry_makeVariableBase (/*@only@*/ cstring name, ctype ct, vkind kind,
4184 sstate defstate, nstate isnull, alkind aliased,
4185 exkind exp, chkind checked,
4186 /*@only@*/ fileloc loc)
4188 uentry e = uentry_alloc ();
4193 e->storageclass = SCNONE;
4195 e->sref = sRef_makeType (ct);
4196 sRef_setNullState (e->sref, isnull, loc);
4198 e->whereDefined = fileloc_undefined;
4200 if (fileloc_isSpec (loc))
4202 e->whereSpecified = loc;
4203 e->whereDeclared = fileloc_undefined;
4207 e->whereSpecified = fileloc_undefined;
4208 e->whereDeclared = loc;
4211 e->isPrivate = FALSE;
4212 e->hasNameError = FALSE;
4217 e->uses = filelocList_new ();
4218 e->warn = warnClause_undefined; /*@i452@*/
4220 e->info = (uinfo) dmalloc (sizeof (*e->info));
4221 e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var));
4222 e->info->var->kind = kind;
4223 e->info->var->checked = checked;
4224 e->info->var->defstate = defstate;
4226 sRef_setDefState (e->sref, defstate, loc);
4228 e->info->var->nullstate = sRef_getNullState (e->sref);
4230 sRef_setExKind (e->sref, exp, loc);
4231 sRef_setAliasKind (e->sref, aliased, loc);
4233 sRef_storeState (e->sref);
4235 /*DRL ADDED 9-1-2000 */
4236 e->info->var->bufinfo = NULL;
4241 static /*@only@*/ uentry
4242 uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, ynm abstract,
4243 ynm mut, ctype rtype, alkind ak, exkind exp,
4244 sstate defstate, nstate isnull,
4245 /*@only@*/ fileloc loc)
4247 uentry e = uentry_alloc ();
4249 e->ukind = KDATATYPE;
4250 /* e->shallowCopy = FALSE; */
4253 e->storageclass = SCNONE;
4254 e->sref = sRef_makeUnknown ();
4255 DPRINTF (("Merge null 1: %s", sRef_unparseFull (e->sref)));
4258 ** This is only setting null state. (I think?)
4261 if (ctype_isUA (ct))
4263 uentry te = usymtab_getTypeEntrySafe (ctype_typeId (ct));
4265 if (uentry_isValid (te))
4267 sRef_setStateFromUentry (e->sref, te);
4271 /* problem for recursive type definitions */
4275 sRef_setAliasKind (e->sref, ak, loc);
4276 sRef_setExKind (e->sref, exp, loc);
4278 sRef_setDefState (e->sref, defstate, loc);
4280 if (ynm_isOn (abstract) && ctype_isUnknown (ct) && isnull == NS_UNKNOWN)
4282 isnull = NS_ABSNULL;
4285 DPRINTF (("Merge null: %s", sRef_unparseFull (e->sref)));
4286 sRef_mergeNullState (e->sref, isnull);
4288 e->whereDefined = fileloc_copy (loc); /*< bogus! (but necessary for lexer) >*/
4290 if (fileloc_isSpec (loc))
4292 e->whereSpecified = loc;
4293 e->whereDeclared = fileloc_undefined;
4297 e->whereSpecified = fileloc_undefined;
4298 e->whereDeclared = loc;
4301 e->isPrivate = FALSE;
4302 e->hasNameError = FALSE;
4304 e->warn = warnClause_undefined; /*@i452@*/
4308 e->uses = filelocList_new ();
4310 e->info = (uinfo) dmalloc (sizeof (*e->info));
4311 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
4312 e->info->datatype->abs = abstract;
4313 e->info->datatype->mut = mut;
4314 e->info->datatype->type = rtype;
4316 DPRINTF (("About to store: %s", sRef_unparseFull (e->sref)));
4317 sRef_storeState (e->sref);
4318 DPRINTF (("After store: %s", sRef_unparseFull (e->sref)));
4324 static void uentry_setHasGlobs (uentry ue)
4326 llassert (uentry_isFunction (ue));
4328 ue->info->fcn->hasGlobs = TRUE;
4331 static void uentry_setHasMods (uentry ue)
4333 llassert (uentry_isFunction (ue));
4335 ue->info->fcn->hasMods = TRUE;
4339 bool uentry_hasGlobs (uentry ue)
4341 if (uentry_isFunction (ue))
4343 return (ue->info->fcn->hasGlobs);
4349 bool uentry_hasStateClauseList (uentry ue)
4351 return (uentry_isFunction (ue) && stateClauseList_isDefined (ue->info->fcn->specclauses));
4354 stateClauseList uentry_getStateClauseList (uentry ue)
4356 if (!uentry_isFunction (ue))
4358 llassert (uentry_isFunction (ue));
4359 return stateClauseList_undefined;
4362 DPRINTF (("Get state clause list: %s", uentry_unparse (ue)));
4363 return ue->info->fcn->specclauses;
4366 bool uentry_hasMods (uentry ue)
4368 if (uentry_isFunction (ue))
4370 return (ue->info->fcn->hasMods);
4377 uentry_makeFunctionBase (/*@only@*/ cstring name, ctype ct,
4379 bool hasGlobs, /*@only@*/ globSet globs,
4380 bool hasMods, /*@only@*/ sRefSet mods,
4381 alkind ak, exkind exp,
4382 sstate defstate, nstate isnull,
4386 /*@only@*/ stateClauseList specclauses,
4387 /*@only@*/ warnClause warnclause,
4388 /*@only@*/ fileloc loc)
4390 uentry e = uentry_alloc ();
4393 /* e->shallowCopy = FALSE; */
4397 e->storageclass = SCNONE;
4399 if (ctype_isFunction (ct))
4401 ret = ctype_getReturnType (ct);
4405 if (ctype_isKnown (ct))
4407 llbug (message ("not function: %s", ctype_unparse (ct)));
4410 ret = ctype_unknown;
4413 e->sref = sRef_makeType (ret);
4415 if (ctype_isUA (ret))
4417 sRef_setStateFromType (e->sref, ret);
4420 sRef_setDefined (e->sref, loc);
4421 sRef_setNullState (e->sref, isnull, loc);
4423 sRef_setAliasKind (e->sref, ak, loc);
4424 sRef_setExKind (e->sref, exp, loc);
4425 sRef_setDefState (e->sref, defstate, loc);
4427 e->whereSpecified = loc;
4428 e->whereDefined = fileloc_undefined;
4430 e->isPrivate = FALSE;
4431 e->hasNameError = FALSE;
4435 e->uses = filelocList_new ();
4436 e->warn = warnclause;
4438 e->info = (uinfo) dmalloc (sizeof (*e->info));
4439 e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn));
4441 e->info->fcn->exitCode = exitCode;
4442 e->info->fcn->specialCode = sCode;
4443 e->info->fcn->nullPred = nullPred;
4444 e->info->fcn->access = access;
4446 e->info->fcn->specclauses = specclauses;
4447 e->info->fcn->hasGlobs = hasGlobs;
4448 e->info->fcn->globs = globs;
4450 e->info->fcn->hasMods = hasMods;
4451 e->info->fcn->mods = mods;
4453 e->info->fcn->defparams = uentryList_undefined;
4454 e->whereDeclared = fileloc_undefined;
4456 sRef_storeState (e->sref);
4459 e->info->fcn->preconditions = NULL;
4463 e->info->fcn->postconditions = NULL;
4469 static /*@only@*/ uentry
4470 uentry_makeTagBase (/*@only@*/ cstring name, ekind tagkind,
4471 ctype ct, ctype rtype, /*@only@*/ fileloc loc)
4473 uentry e = uentry_alloc ();
4475 if (tagkind != KSTRUCTTAG && tagkind != KUNIONTAG && tagkind != KENUMTAG)
4477 llbuglit ("uentry_makeTagBase: not a tag type");
4480 /* e->shallowCopy = FALSE; */
4484 e->sref = sRef_makeUnknown ();
4485 e->storageclass = SCNONE;
4487 if (fileloc_isSpec (loc))
4489 e->whereSpecified = loc;
4490 e->whereDeclared = fileloc_undefined;
4494 e->whereDeclared = loc;
4495 e->whereSpecified = fileloc_undefined;
4498 e->whereDefined = fileloc_undefined;
4500 e->isPrivate = FALSE;
4501 e->hasNameError = FALSE;
4505 e->uses = filelocList_new ();
4506 e->warn = warnClause_undefined; /*@i452@*/
4508 e->info = (uinfo) dmalloc (sizeof (*e->info));
4509 e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype));
4510 e->info->datatype->abs = NO;
4511 e->info->datatype->mut = MAYBE;
4512 e->info->datatype->type = rtype;
4514 sRef_storeState (e->sref);
4520 uentry_makeIterBase (/*@only@*/ cstring name, typeIdSet access,
4521 ctype ct, /*@only@*/ fileloc loc)
4523 uentry e = uentry_alloc ();
4525 /* e->shallowCopy = FALSE; */
4529 e->sref = sRef_makeUnknown ();
4530 e->storageclass = SCNONE;
4532 if (fileloc_isSpec (loc))
4534 e->whereSpecified = loc;
4535 e->whereDeclared = fileloc_undefined;
4539 e->whereDeclared = loc;
4540 e->whereSpecified = fileloc_undefined;
4543 e->whereDefined = fileloc_undefined;
4545 e->isPrivate = FALSE;
4546 e->hasNameError = FALSE;
4550 e->uses = filelocList_new ();
4551 e->warn = warnClause_undefined; /*@i452@*/
4553 e->info = (uinfo) dmalloc (sizeof (*e->info));
4554 e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter));
4555 e->info->iter->access = access;
4556 e->info->iter->mods = sRefSet_undefined;
4557 e->info->iter->globs = globSet_undefined;
4559 sRef_storeState (e->sref);
4564 uentry_makeEndIterBase (/*@only@*/ cstring name, typeIdSet access,
4565 /*@only@*/ fileloc loc)
4567 uentry e = uentry_alloc ();
4569 /* e->shallowCopy = FALSE; */
4570 e->ukind = KENDITER;
4571 e->storageclass = SCNONE;
4573 e->utype = ctype_unknown;
4574 e->sref = sRef_makeUnknown ();
4576 if (fileloc_isSpec (loc))
4578 e->whereSpecified = loc;
4579 e->whereDeclared = fileloc_undefined;
4583 e->whereDeclared = loc;
4584 e->whereSpecified = fileloc_undefined;
4587 e->whereDefined = fileloc_undefined;
4589 e->isPrivate = FALSE;
4590 e->hasNameError = FALSE;
4594 e->uses = filelocList_new ();
4595 e->warn = warnClause_undefined; /*@i452@*/
4597 e->info = (uinfo) dmalloc (sizeof (*e->info));
4598 e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer));
4599 e->info->enditer->access = access;
4600 sRef_storeState (e->sref);
4605 void uentry_markFree (/*@unused@*/ /*@owned@*/ uentry u)
4613 uentry_undump (ekind kind, fileloc loc, char **s)
4617 DPRINTF (("Uentry undump: %s", *s));
4621 reader_checkChar (s, '!');
4622 reader_checkChar (s, '.');
4623 ue = uentry_makeElipsisMarker ();
4627 ctype ct = ctype_undump (s);
4641 reader_checkChar (s, '|');
4643 if (reader_optCheckChar (s, '@'))
4645 tkind = vkind_fromInt (reader_getInt (s));
4646 reader_checkChar (s, '|');
4653 if (reader_optCheckChar (s, '$'))
4655 defstate = SS_UNKNOWN;
4656 isnull = NS_UNKNOWN;
4657 aliased = AK_IMPTEMP;
4659 checked = CH_UNKNOWN;
4661 else if (reader_optCheckChar (s, '&'))
4663 defstate = SS_DEFINED;
4664 isnull = NS_UNKNOWN;
4665 aliased = AK_IMPTEMP;
4667 checked = CH_UNKNOWN;
4669 else if (reader_optCheckChar (s, '^'))
4671 defstate = SS_UNKNOWN;
4672 isnull = NS_UNKNOWN;
4673 aliased = AK_IMPTEMP;
4675 checked = CH_UNKNOWN;
4679 defstate = sstate_fromInt (reader_getInt (s));
4680 advanceField (s); isnull = nstate_fromInt (reader_getInt (s));
4681 advanceField (s); aliased = alkind_fromInt (reader_getInt (s));
4683 if (reader_optCheckChar (s, '&'))
4686 checked = CH_UNKNOWN;
4690 advanceField (s); exp = exkind_fromInt (reader_getInt (s));
4691 advanceField (s); checked = (chkind) (reader_getInt (s));
4696 name = reader_getStringWord (s);
4698 llassert (!cstring_equal (name, GLOBAL_MARKER_NAME));
4700 ue = uentry_makeVariableBase (name, ct, tkind, defstate,
4701 isnull, aliased, exp,
4702 checked, fileloc_copy (loc));
4715 advanceField (s); abstract = ynm_fromCodeChar (reader_loadChar (s));
4716 advanceField (s); mut = ynm_fromCodeChar (reader_loadChar (s));
4717 advanceField (s); defstate = sstate_fromInt (reader_getInt (s));
4718 advanceField (s); isnull = nstate_fromInt (reader_getInt (s));
4719 advanceField (s); aliased = alkind_fromInt (reader_getInt (s));
4720 advanceField (s); exp = exkind_fromInt (reader_getInt (s));
4721 advanceField (s); rtype = ctype_undump (s);
4723 name = reader_getStringWord (s);
4724 DPRINTF (("Datatype %s, Exp = %s", name, exkind_unparse (exp)));
4725 ue = uentry_makeDatatypeBase (name, ct, abstract, mut, rtype,
4726 aliased, exp, defstate, isnull,
4727 fileloc_copy (loc));
4744 stateClauseList specclauses = stateClauseList_undefined;
4745 warnClause warnclause = warnClause_undefined;
4747 if (reader_optCheckChar (s, '$'))
4749 defstate = SS_DEFINED;
4750 isnull = NS_UNKNOWN;
4751 exitCode = XK_UNKNOWN;
4753 nullPred = qual_createUnknown ();
4757 advanceField (s); defstate = sstate_fromInt (reader_getInt (s));
4758 advanceField (s); isnull = nstate_fromInt (reader_getInt (s));
4759 advanceField (s); exitCode = exitkind_fromInt (reader_getInt (s));
4760 advanceField (s); specc = specCode_fromInt (reader_getInt (s));
4761 advanceField (s); nullPred = qual_undump (s);
4764 if (reader_optCheckChar (s, '$'))
4767 globs = globSet_undefined;
4769 mods = sRefSet_undefined;
4771 else if (reader_optCheckChar (s, '^'))
4774 globs = globSet_undefined;
4776 mods = sRefSet_undefined;
4780 advanceField (s); hasGlobs = bool_fromInt (reader_getInt (s));
4781 advanceField (s); globs = globSet_undump (s);
4782 advanceField (s); hasMods = bool_fromInt (reader_getInt (s));
4783 advanceField (s); mods = sRefSet_undump (s);
4786 if (reader_optCheckChar (s, '$'))
4793 advanceField (s); ak = alkind_fromInt (reader_getInt (s));
4794 advanceField (s); exp = exkind_fromInt (reader_getInt (s));
4797 advanceField (s); access = typeIdSet_undump (s);
4800 ** Optional clauses: Start with @<code>:
4803 while (reader_optCheckChar (s, '@'))
4805 if (reader_optCheckChar (s, 'W')) /* Warn clause */
4807 reader_checkChar (s, ':');
4808 warnclause = warnClause_undump (s);
4810 else if (reader_optCheckChar (s, 'S')) /* stateClause List */
4812 reader_checkChar (s, ':');
4813 specclauses = stateClauseList_undump (s);
4821 advanceName (s); name = reader_getStringWord (s);
4823 ue = uentry_makeFunctionBase (name, ct, access,
4826 ak, exp, defstate, isnull,
4827 exitCode, specc, nullPred,
4830 fileloc_copy (loc));
4831 DPRINTF (("Undump: %s", uentry_unparse (ue)));
4838 advanceField (s); access = typeIdSet_undump (s);
4839 advanceName (s); name = reader_getStringWord (s);
4841 ue = uentry_makeIterBase (name, access, ct,
4842 fileloc_copy (loc));
4849 advanceField (s); access = typeIdSet_undump (s);
4850 advanceName (s); name = reader_getStringWord (s);
4852 ue = uentry_makeEndIterBase (name, access, fileloc_copy (loc));
4862 if (reader_optCheckChar (s, '$'))
4864 val = multiVal_undefined;
4865 access = typeIdSet_undefined;
4866 nullstate = NS_UNKNOWN;
4870 advanceField (s); val = multiVal_undump (s);
4871 advanceField (s); access = typeIdSet_undump (s);
4872 advanceField (s); nullstate = nstate_fromInt (reader_getInt (s));
4875 advanceName (s); name = reader_getStringWord (s);
4877 ue = uentry_makeConstantBase (name, ct, access,
4878 nullstate, fileloc_copy (loc), val);
4887 advanceField (s); rtype = ctype_undump (s);
4888 advanceName (s); name = reader_getStringWord (s);
4889 ue = uentry_makeTagBase (name, kind, ct, rtype, fileloc_copy (loc));
4893 llcontbuglit ("uentry_undump: invalid");
4894 ue = uentry_undefined;
4897 llcontbuglit ("uentry_undump: elips marker");
4898 ue = uentry_undefined;
4907 uentry_dump (uentry v)
4909 return (uentry_dumpAux (v, FALSE));
4913 uentry_dumpParam (uentry v)
4915 llassertprint (uentry_isVariable (v) || uentry_isElipsisMarker (v),
4916 ("dump: %s", uentry_unparseFull (v)));
4918 return (uentry_dumpAux (v, TRUE));
4922 uentry_dumpAux (uentry v, bool isParam)
4924 llassert (uentry_isValid (v));
4925 llassert (!uentry_isGlobalMarker (v));
4927 DPRINTF (("Dump uentry: [%p]", v));
4928 DPRINTF (("Dumping entry: %s", uentry_unparseFull (v)));
4933 llcontbuglit ("uentry_dump: invalid entry");
4934 return cstring_undefined;
4936 return (message ("!."));
4940 vkind vk = v->info->var->kind;
4941 sstate dss = sRef_getDefState (v->sref);
4942 nstate nst = sRef_getNullState (v->sref);
4943 alkind alk = sRef_getAliasKind (v->sref);
4944 exkind exk = sRef_getExKind (v->sref);
4945 chkind chk = v->info->var->checked;
4947 DPRINTF (("Dumping var"));
4949 if (dss == SS_UNKNOWN
4950 && nst == NS_UNKNOWN
4951 && alk == AK_IMPTEMP
4952 && exk == XO_UNKNOWN
4953 && chk == CH_UNKNOWN)
4955 sdump = cstring_makeLiteral ("$");
4957 else if (dss == SS_DEFINED
4958 && nst == NS_UNKNOWN
4959 && alk == AK_IMPTEMP
4960 && exk == XO_UNKNOWN
4961 && chk == CH_UNKNOWN)
4963 sdump = cstring_makeLiteral ("&");
4965 else if (dss == SS_UNKNOWN
4966 && nst == NS_UNKNOWN
4967 && alk == AK_UNKNOWN
4968 && exk == XO_UNKNOWN
4969 && chk == CH_UNKNOWN)
4971 sdump = cstring_makeLiteral ("^");
4973 else if (exk == XO_UNKNOWN
4974 && chk == CH_UNKNOWN)
4976 sdump = message ("%d@%d@%d&",
4983 sdump = message ("%d@%d@%d@%d@%d",
4994 return (message ("%q|@%d|%q#%s",
4995 ctype_dump (v->utype),
4998 isParam ? cstring_undefined : v->uname));
5002 return (message ("%q|%q#%s",
5003 ctype_dump (v->utype),
5005 isParam ? cstring_undefined : v->uname));
5011 DPRINTF (("Dumping datatype: %s -> %s type: %s [%d]",
5013 exkind_unparse (sRef_getExKind (v->sref)),
5014 ctype_unparse (v->utype), (int) v->utype));
5017 return (message ("%q@%s@%s@%d@%d@%d@%d@%q#%s",
5018 ctype_dump (v->utype),
5019 ynm_unparseCode (v->info->datatype->abs),
5020 ynm_unparseCode (v->info->datatype->mut),
5021 (int) sRef_getDefState (v->sref),
5022 (int) sRef_getNullState (v->sref),
5023 (int) sRef_getAliasKind (v->sref),
5024 (int) sRef_getExKind (v->sref),
5025 ctype_dump (v->info->datatype->type),
5029 cstring sdump, gdump, adump, xdump;
5030 alkind alk = sRef_getAliasKind (v->sref);
5031 exkind exk = sRef_getExKind (v->sref);
5033 if (sRef_getDefState (v->sref) == SS_DEFINED
5034 && !nstate_isKnown (sRef_getNullState (v->sref))
5035 && !exitkind_isKnown (v->info->fcn->exitCode)
5036 && v->info->fcn->specialCode == SPC_NONE
5037 && qual_isUnknown (v->info->fcn->nullPred))
5039 sdump = cstring_makeLiteral ("$");
5043 sdump = message ("@%d@%d@%d@%d@%x",
5044 (int) sRef_getDefState (v->sref),
5045 (int) sRef_getNullState (v->sref),
5046 (int) v->info->fcn->exitCode,
5047 (int) v->info->fcn->specialCode,
5048 qual_dump (v->info->fcn->nullPred));
5051 if (!uentry_hasGlobs(v) && !uentry_hasMods (v))
5053 gdump = cstring_makeLiteral ("$");
5055 else if (uentry_hasGlobs (v) && globSet_isEmpty (uentry_getGlobs (v))
5056 && uentry_hasMods (v) && sRefSet_isEmpty (uentry_getMods (v)))
5058 gdump = cstring_makeLiteral ("^");
5062 gdump = message ("@%s@%q@%s@%q",
5063 bool_dump (uentry_hasGlobs (v)),
5064 globSet_dump (uentry_getGlobs (v)),
5065 bool_dump (uentry_hasMods (v)),
5066 sRefSet_dump (uentry_getMods (v)));
5069 if (alk == AK_UNKNOWN && exk == XO_UNKNOWN)
5071 adump = cstring_makeLiteral ("$");
5075 adump = message ("@%d@%d", (int) alk, (int) exk);
5078 xdump = cstring_undefined;
5080 if (uentry_hasWarning (v))
5082 xdump = message ("%q@W:%q", xdump, warnClause_dump (v->warn));
5085 if (uentry_hasStateClauseList (v))
5087 xdump = message ("%q@S:%q", xdump, stateClauseList_dump (v->info->fcn->specclauses));
5090 return (message ("%q%q%q%q@%q%q#%s",
5091 ctype_dump (v->utype),
5095 typeIdSet_dump (uentry_accessType (v)),
5100 return (message ("%q@%q#%s",
5101 ctype_dump (v->utype),
5102 typeIdSet_dump (v->info->iter->access),
5105 return (message ("%q@%q#%s",
5106 ctype_dump (v->utype),
5107 typeIdSet_dump (uentry_accessType (v)),
5114 if (multiVal_isUnknown (v->info->uconst->val)
5115 && typeIdSet_isEmpty (uentry_accessType (v))
5116 && (sRef_getNullState (v->sref) == NS_UNKNOWN))
5118 sdump = cstring_makeLiteral ("$");
5122 sdump = message ("@%q@%q@%d",
5123 multiVal_dump (v->info->uconst->val),
5124 typeIdSet_dump (uentry_accessType (v)),
5125 (int) sRef_getNullState (v->sref));
5128 return (message ("%q%q#%s",
5129 ctype_dump (v->utype),
5136 return (message ("%q@%q#%s",
5137 ctype_dump (v->utype),
5138 ctype_dump (v->info->datatype->type), v->uname));
5145 uentry_unparseAbbrev (uentry v)
5147 if (!uentry_isVariable (v))
5149 llcontbuglit ("uentry_unparseAbbrev: not variable");
5150 return uentry_unparse (v);
5153 return (message ("%s %q", ctype_unparseDeep (v->utype), uentry_getName (v)));
5157 uentry_unparse (uentry v)
5161 if (uentry_isUndefined (v)) return (cstring_makeLiteral ("<undefined>"));
5162 if (uentry_isElipsisMarker (v)) return (cstring_makeLiteral ("..."));
5164 st = uentry_getName (v);
5166 if (cstring_isDefined (st))
5168 return (ctype_unparseDeclaration (v->utype, st));
5173 return (cstring_copy (ctype_unparse (v->utype)));
5178 uentry_unparseFull (uentry v)
5180 if (uentry_isUndefined (v))
5182 return (cstring_makeLiteral ("<undefined>"));
5188 res = message ("[%w] %s %s: %s [spec: %q; decl: %q; def: %q]",
5189 (unsigned long) v, ekind_unparse (v->ukind), v->uname,
5190 ctype_unparse (v->utype),
5191 fileloc_unparse (uentry_whereSpecified (v)),
5192 fileloc_unparse (uentry_whereDeclared (v)),
5193 fileloc_unparse (uentry_whereDefined (v)));
5195 DPRINTF (("uentry: %s", res));
5197 if (uentry_isDatatype (v))
5199 res = message ("%q / type: %s mut: %s abs: %s state: %q",
5202 (ctype_isDefined (v->info->datatype->type)
5203 ? v->info->datatype->type : ctype_unknown),
5204 ynm_unparse (v->info->datatype->mut),
5205 ynm_unparse (v->info->datatype->abs),
5206 sRef_unparseState (v->sref));
5208 else if (uentry_isFunction (v))
5210 res = message ("%q / sref: %q / mods: %q / "
5211 "globs: %q / clauses: %q / pre: %q / post: %q",
5213 sRef_unparseFull (v->sref),
5214 sRefSet_unparse (v->info->fcn->mods),
5215 globSet_unparse (v->info->fcn->globs),
5216 stateClauseList_unparse (v->info->fcn->specclauses),
5217 functionConstraint_unparse (v->info->fcn->preconditions),
5218 functionConstraint_unparse (v->info->fcn->postconditions));
5220 else if (uentry_isIter (v))
5222 res = message ("%q / sref: %q",
5224 sRef_unparseFull (v->sref));
5226 else if (uentry_isVariable (v))
5228 res = message ("%q / sref: %q / kind <%d> isout <%d> null <%d> used <%d>",
5230 sRef_unparseFull (v->sref),
5231 (int) v->info->var->kind,
5232 (int) v->info->var->defstate,
5233 (int) v->info->var->nullstate,
5235 DPRINTF (("sref: [%p]", v->sref));
5236 DPRINTF (("sref: %s", sRef_unparseDebug (v->sref)));
5237 /* DPRINTF (("sref: %s", sRef_unparseDeep (v->sref))); */
5241 res = message ("%q :: %q", res, uentry_unparse (v));
5248 bool uentry_hasAccessType (uentry e)
5250 if (uentry_isValid (e))
5255 return (!typeIdSet_isEmpty (e->info->iter->access));
5257 return (!typeIdSet_isEmpty (e->info->enditer->access));
5259 return (!typeIdSet_isEmpty (e->info->fcn->access));
5262 return (!typeIdSet_isEmpty (e->info->uconst->access));
5271 typeIdSet uentry_accessType (uentry e)
5273 if (uentry_isValid (e))
5278 return (e->info->iter->access);
5280 return (e->info->enditer->access);
5282 return (e->info->fcn->access);
5285 return (e->info->uconst->access);
5291 return typeIdSet_undefined;
5295 uentry_isVariable (uentry e)
5297 return (uentry_isVar (e));
5301 uentry_isSpecified (uentry e)
5303 return (uentry_isValid (e) && !fileloc_isUndefined (e->whereSpecified));
5307 uentry_isReallySpecified (uentry e)
5309 return (uentry_isValid (e)
5310 && fileloc_isRealSpec (e->whereSpecified));
5314 uentry_isVar (uentry e)
5316 return (!uentry_isUndefined (e) && e->ukind == KVAR);
5320 uentry_isFakeTag (uentry e)
5322 return (uentry_isValid (e) && strchr (cstring_toCharsSafe (e->uname), '!') != 0);
5326 uentry_isDatatype (uentry e)
5328 return (!uentry_isUndefined (e) &&
5329 (e->ukind == KDATATYPE || e->ukind == KSTRUCTTAG ||
5330 e->ukind == KUNIONTAG || e->ukind == KENUMTAG));
5334 uentry_setAbstract (uentry e)
5338 llassert (uentry_isDatatype (e)
5339 && (ynm_isMaybe (e->info->datatype->abs)));
5341 oldid = ctype_typeId (e->info->datatype->type);
5342 e->info->datatype->abs = YES;
5343 e->info->datatype->type = ctype_createAbstract (oldid);
5347 uentry_setConcrete (uentry e)
5349 llassert (uentry_isDatatype (e)
5350 && (ynm_isMaybe (e->info->datatype->abs)));
5352 e->info->datatype->abs = NO;
5356 uentry_isAbstractDatatype (uentry e)
5358 return (uentry_isDatatype (e)
5359 && (ynm_isOn (e->info->datatype->abs)));
5363 uentry_isMaybeAbstract (uentry e)
5365 return (uentry_isDatatype (e)
5366 && (ynm_isMaybe (e->info->datatype->abs)));
5370 uentry_isMutableDatatype (uentry e)
5372 bool res = uentry_isDatatype (e)
5373 && (ynm_toBoolRelaxed (e->info->datatype->mut));
5379 uentry_isRefCountedDatatype (uentry e)
5381 return (uentry_isDatatype (e) && (sRef_isRefCounted (uentry_getSref (e))));
5385 uentry_isParam (uentry u)
5387 return (uentry_isVariable (u) && (u->info->var->kind == VKPARAM
5388 || u->info->var->kind == VKYIELDPARAM));
5392 uentry_isExpandedMacro (uentry u)
5394 return (uentry_isVariable (u) && (u->info->var->kind == VKEXPMACRO));
5398 uentry_isSefParam (uentry u)
5400 return (uentry_isVariable (u)
5401 && (u->info->var->kind == VKSEFPARAM
5402 || u->info->var->kind == VKREFSEFPARAM
5403 || u->info->var->kind == VKSEFRETPARAM
5404 || u->info->var->kind == VKREFSEFRETPARAM));
5408 uentry_isRefParam (uentry u)
5410 return (uentry_isVariable (u)
5411 && (u->info->var->kind == VKREFPARAM
5412 || u->info->var->kind == VKREFYIELDPARAM
5413 || u->info->var->kind == VKREFSEFPARAM
5414 || u->info->var->kind == VKREFSEFRETPARAM));
5418 uentry_isAnyParam (uentry u)
5420 return (uentry_isVariable (u)
5421 && ((u->info->var->kind == VKPARAM)
5422 || (u->info->var->kind == VKSEFPARAM)
5423 || (u->info->var->kind == VKYIELDPARAM)
5424 || (u->info->var->kind == VKRETPARAM)
5425 || (u->info->var->kind == VKSEFRETPARAM)));
5429 uentry_getDefState (uentry u)
5431 if (uentry_isValid (u))
5433 return (sRef_getDefState (u->sref));
5437 return (SS_UNKNOWN);
5442 uentry_isOut (uentry u)
5444 return ((uentry_isVariable (u) && (u->info->var->defstate == SS_ALLOCATED))
5445 || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
5449 uentry_isPartial (uentry u)
5451 return ((uentry_isVariable (u) && (u->info->var->defstate == SS_PARTIAL))
5452 || (uentry_isDatatype (u) && (sRef_isAllocated (u->sref))));
5456 uentry_isStateSpecial (uentry u)
5458 return ((uentry_isVariable (u)
5459 && (u->info->var->defstate == SS_SPECIAL))
5460 || (uentry_isValid (u) && sRef_isStateSpecial (u->sref)));
5463 exitkind uentry_getExitCode (uentry ue)
5465 if (uentry_isFunction (ue))
5467 return ue->info->fcn->exitCode;
5475 qual uentry_nullPred (uentry u)
5477 llassert (uentry_isRealFunction (u));
5479 if (uentry_isFunction (u))
5481 return (u->info->fcn->nullPred);
5485 return qual_createUnknown ();
5490 ** Note for variables, this is checking the declared state, not the current state.
5494 uentry_possiblyNull (uentry u)
5496 return ((uentry_isVariable (u) && (nstate_possiblyNull (u->info->var->nullstate)))
5497 || (uentry_isDatatype (u) && (sRef_possiblyNull (u->sref))));
5501 uentry_getAliasKind (uentry u)
5503 if (uentry_isValid (u))
5505 return (sRef_getAliasKind (uentry_getSref (u)));
5514 uentry_getExpKind (uentry u)
5516 if (uentry_isValid (u))
5518 return (sRef_getExKind (uentry_getSref (u)));
5527 uentry_isIter (uentry e)
5529 return (!uentry_isUndefined (e) && e->ukind == KITER);
5533 uentry_isEndIter (uentry e)
5535 return (!uentry_isUndefined (e) && e->ukind == KENDITER);
5539 uentry_isRealFunction (uentry e)
5541 return (uentry_isFunction (e) ||
5542 (uentry_isVariable (e) && ctype_isFunction (uentry_getType (e))));
5546 uentry_hasName (uentry e)
5548 if (uentry_isValid (e))
5550 cstring s = e->uname;
5552 return (!(cstring_isEmpty (s) || cstring_equalLit (s, "...")
5553 || uentry_isFakeTag (e)));
5562 ** Returns true for fake tags.
5563 ** This is used for dumping the library
5566 bool uentry_hasRealName (uentry e)
5568 return (uentry_isValid (e)
5569 && cstring_isNonEmpty (e->uname)
5570 && !uentry_isGlobalMarker (e));
5574 /*@observer@*/ globSet
5575 uentry_getGlobs (uentry l)
5577 if (uentry_isInvalid (l))
5579 return globSet_undefined;
5582 if (l->ukind != KFCN)
5584 if (l->ukind != KITER && l->ukind != KENDITER)
5586 if (l->ukind == KVAR)
5588 llbug (message ("Bad call to uentry_getGlobs (var): %q (%s)",
5590 ekind_unparse (l->ukind)));
5594 llbug (message ("Bad call to uentry_getGlobs: %q (%s)",
5596 ekind_unparse (l->ukind)));
5599 return globSet_undefined;
5602 return l->info->fcn->globs;
5605 /*@observer@*/ sRefSet
5606 uentry_getMods (uentry l)
5608 llassert (uentry_isValid (l));
5610 if (l->ukind != KFCN && l->ukind != KITER && l->ukind != KENDITER)
5612 llcontbug (message ("Bad call to uentry_getMods: %q", uentry_unparse (l)));
5613 return sRefSet_undefined;
5616 return l->info->fcn->mods;
5620 uentry_getKind (uentry e)
5622 llassert (uentry_isValid (e));
5627 /*@observer@*/ multiVal uentry_getConstantValue (uentry e)
5629 llassert (uentry_isEitherConstant (e));
5631 return (e->info->uconst->val);
5634 /*@observer@*/ uentryList
5635 uentry_getParams (uentry l)
5637 if (uentry_isInvalid (l)) return uentryList_undefined;
5644 ctype ct = l->utype;
5646 if (ctype_isFunction (ct))
5648 return (ctype_argsFunction (ct));
5652 return uentryList_undefined;
5657 ctype ct = l->utype;
5659 llassert (ctype_isFunction (ct));
5660 return (ctype_argsFunction (ct));
5667 /*@observer@*/ cstring
5668 uentry_rawName (uentry e)
5670 if (uentry_isValid (e))
5676 return cstring_undefined;
5681 uentry_getOptName (uentry e)
5683 cstring s = uentry_getName (e);
5685 if (cstring_isDefined (s))
5687 s = cstring_appendChar (s, ' ');
5694 uentry_getName (uentry e)
5696 cstring ret = cstring_undefined;
5698 if (uentry_isValid (e))
5700 if (uentry_isAnyTag (e))
5702 ret = fixTagName (e->uname);
5704 else if (uentry_isAnyParam (e))
5706 ret = cstring_copy (fixParamName (e->uname));
5710 ret = cstring_copy (e->uname);
5717 cstring uentry_observeRealName (uentry e)
5719 cstring ret = cstring_undefined;
5721 if (uentry_isValid (e))
5723 if (uentry_isAnyTag (e))
5725 if (isFakeTag (e->uname))
5727 ret = cstring_undefined;
5731 ret = plainTagName (e->uname);
5734 else if (uentry_isAnyParam (e))
5736 ret = fixParamName (e->uname);
5747 cstring uentry_getRealName (uentry e)
5749 if (uentry_isValid (e))
5751 if (uentry_isAnyTag (e))
5753 return (cstring_undefined);
5760 return cstring_undefined;
5763 ctype uentry_getType (uentry e)
5765 if (uentry_isValid (e))
5771 return ctype_unknown;
5775 fileloc uentry_whereLast (uentry e)
5779 if (uentry_isInvalid (e))
5781 return fileloc_undefined;
5784 loc = e->whereDefined;
5786 if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
5791 loc = uentry_whereDeclared (e);
5793 if (fileloc_isValid (loc) && !fileloc_isExternal (loc))
5798 loc = uentry_whereSpecified (e);
5802 fileloc uentry_whereEither (uentry e)
5804 if (uentry_isInvalid (e)) return fileloc_undefined;
5806 if (fileloc_isDefined (e->whereDefined)
5807 && !fileloc_isExternal (e->whereDefined))
5809 return e->whereDefined;
5811 else if (fileloc_isDefined (e->whereDeclared))
5813 return e->whereDeclared;
5817 return e->whereSpecified;
5821 fileloc uentry_whereSpecified (uentry e)
5823 if (uentry_isInvalid (e)) return fileloc_undefined;
5825 return (e->whereSpecified);
5828 fileloc uentry_whereDefined (uentry e)
5830 if (uentry_isInvalid (e)) return fileloc_undefined;
5832 return (e->whereDefined);
5835 fileloc uentry_whereDeclared (uentry e)
5837 if (uentry_isInvalid (e)) return fileloc_undefined;
5839 return (e->whereDeclared);
5842 /*@observer@*/ fileloc
5843 uentry_whereEarliest (uentry e)
5845 if (uentry_isInvalid (e)) return fileloc_undefined;
5847 if (fileloc_isDefined (e->whereSpecified))
5849 return (e->whereSpecified);
5851 else if (fileloc_isDefined (e->whereDeclared))
5853 return (e->whereDeclared);
5857 return e->whereDefined;
5862 uentry_setFunctionDefined (uentry e, fileloc loc)
5864 if (uentry_isValid (e))
5866 llassert (uentry_isFunction (e));
5868 if (fileloc_isUndefined (e->whereDeclared))
5870 e->whereDeclared = fileloc_update (e->whereDeclared, loc);
5873 if (!fileloc_isDefined (e->whereDefined))
5875 e->whereDefined = fileloc_update (e->whereDefined, loc);
5881 uentry_setDeclDef (uentry e, fileloc f)
5883 uentry_setDeclared (e, f);
5885 if (!uentry_isFunction (e)
5886 && !(uentry_isVariable (e) && uentry_isExtern (e)))
5888 uentry_setDefined (e, f);
5893 uentry_setDeclaredForce (uentry e, fileloc f)
5895 llassert (uentry_isValid (e));
5896 e->whereDeclared = fileloc_update (e->whereDeclared, f);
5900 uentry_setDeclaredForceOnly (uentry e, fileloc f)
5902 llassert (uentry_isValid (e));
5903 fileloc_free (e->whereDeclared);
5904 e->whereDeclared = f;
5908 uentry_setDeclaredOnly (uentry e, /*@only@*/ fileloc f)
5912 llassert (uentry_isValid (e));
5913 oldloc = e->whereDeclared;
5915 if (fileloc_isDefined (oldloc))
5917 if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
5919 e->whereDeclared = f;
5920 fileloc_free (oldloc);
5929 e->whereDeclared = f;
5930 fileloc_free (oldloc);
5935 uentry_setDeclared (uentry e, fileloc f)
5939 llassert (uentry_isValid (e));
5940 oldloc = e->whereDeclared;
5942 if (fileloc_isDefined (oldloc))
5944 if (fileloc_isLib (oldloc) || fileloc_isImport (oldloc))
5946 e->whereDeclared = fileloc_update (e->whereDeclared, f);
5955 e->whereDeclared = fileloc_update (e->whereDeclared, f);
5960 uentry_clearDefined (uentry e)
5962 if (uentry_isValid (e))
5964 e->whereDefined = fileloc_update (e->whereDefined, fileloc_undefined);
5969 uentry_setDefined (uentry e, fileloc f)
5973 llassert (uentry_isValid (e));
5974 oldloc = e->whereDefined;
5976 if (fileloc_isDefined (oldloc))
5978 if (fileloc_isLib (oldloc)
5979 || fileloc_isImport (oldloc)
5980 || fileloc_isBuiltin (oldloc)
5981 || fileloc_isPreproc (oldloc))
5983 e->whereDefined = fileloc_update (e->whereDefined, f);
5987 if (fileloc_equal (oldloc, f) || context_processingMacros ())
5993 if (optgenerror (FLG_REDEF,
5994 message ("%s %q redefined",
5995 ekind_capName (e->ukind),
5996 uentry_getName (e)),
5999 llgenindentmsg (message ("Previous definition of %q",
6000 uentry_getName (e)),
6008 e->whereDefined = fileloc_update (e->whereDefined, f);
6013 uentry_isCodeDefined (uentry e)
6015 return (uentry_isValid (e) && fileloc_isDefined (e->whereDefined));
6019 uentry_isDeclared (uentry e)
6021 if (uentry_isValid (e))
6023 return (fileloc_isDefined (e->whereDeclared));
6029 sRef uentry_getSref (uentry e)
6031 /* not true, used for functions too (but shouldn't be? */
6032 /* llassertprint (e->ukind == KVAR, ("uentry_getSref: not variable!")); */
6034 if (uentry_isInvalid (e)) return sRef_undefined;
6039 sRef uentry_getOrigSref (uentry e)
6041 if (uentry_isValid (e))
6043 sRef sr = sRef_copy (uentry_getSref (e));
6045 sRef_resetState (sr);
6046 sRef_clearDerived (sr);
6048 if (uentry_isVariable (e))
6050 sRef_setDefState (sr, e->info->var->defstate, fileloc_undefined);
6051 sRef_setNullState (sr, e->info->var->nullstate, fileloc_undefined);
6058 return sRef_undefined;
6063 ** requires: uentry e is not in a hashed symbol table
6067 uentry_setName (uentry e, /*@only@*/ cstring n)
6069 llassert (uentry_isValid (e));
6071 cstring_free (e->uname);
6076 uentry_setType (uentry e, ctype t)
6078 if (uentry_isValid (e))
6081 sRef_setType (e->sref, t);
6086 uentry_resetParams (uentry ue, /*@only@*/ uentryList pn)
6089 ctype rettype = ctype_unknown;
6091 llassert (uentry_isValid (ue));
6093 rct = ctype_realType (ue->utype);
6095 if (uentry_isVariable (ue) && (ctype_isFunction (rct) || ctype_isUnknown (rct)))
6097 uentry_makeVarFunction (ue);
6100 llassert (uentry_isFunction (ue));
6102 if (ctype_isFunction (rct))
6104 rettype = ctype_getReturnType (rct);
6107 ue->utype = ctype_makeNFParamsFunction (rettype, pn);
6111 uentry_setRefParam (uentry e)
6114 if (!uentry_isVar (e))
6116 llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
6120 if (e->info->var->kind == VKSEFPARAM)
6122 e->info->var->kind = VKREFSEFPARAM;
6124 else if (e->info->var->kind == VKSEFRETPARAM)
6126 e->info->var->kind = VKREFSEFRETPARAM;
6128 else if (e->info->var->kind == VKYIELDPARAM)
6130 e->info->var->kind = VKREFYIELDPARAM;
6134 e->info->var->kind = VKREFPARAM;
6140 uentry_setParam (uentry e)
6142 if (!uentry_isVar (e))
6144 if (uentry_isElipsisMarker (e))
6150 llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e)));
6157 if (e->info->var->kind == VKYIELDPARAM
6158 || e->info->var->kind == VKSEFPARAM
6159 || e->info->var->kind == VKSEFRETPARAM)
6165 e->info->var->kind = VKPARAM;
6169 e->uname = makeParam (e->uname);
6170 cstring_free (oldname);
6175 uentry_setSref (uentry e, sRef s)
6177 if (uentry_isValid (e))
6179 if (sRef_isValid (e->sref))
6181 sRef_mergeStateQuietReverse (e->sref, s);
6185 e->sref = sRef_saveCopy (s);
6191 uentry_getAbstractType (uentry e)
6193 llassert (uentry_isDatatype (e));
6196 ** This assertion removed.
6197 ** Okay to have undefined type, for system types
6199 llassertprintret (!ctype_isUndefined (e->info->datatype->type),
6200 ("uentry_getAbstractType %q: undefined", uentry_unparseFull (e)),
6205 if (ctype_isUndefined (e->info->datatype->type))
6207 return ctype_unknown;
6211 ** Sadly, a kludge...
6214 if (ctype_isUserBool (e->info->datatype->type)) {
6218 return e->info->datatype->type;
6221 ctype uentry_getRealType (uentry e)
6224 typeId uid = USYMIDINVALID;
6226 if (uentry_isInvalid (e))
6228 return ctype_unknown;
6231 llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e)));
6233 if (uentry_isAnyTag (e))
6238 if (uentry_isAbstractType (e))
6240 ct = uentry_getAbstractType (e);
6242 if (ctype_isManifestBool (ct)) {
6246 llassert (ctype_isUA (ct));
6248 uid = ctype_typeId (ct);
6250 if (!context_hasAccess (uid))
6256 ct = uentry_getType (e);
6258 /* if (ctype_isUserBool (ct)) return ct; */
6260 if (ctype_isManifestBool (ct)) {
6264 if (ctype_isUA (ct))
6266 usymId iid = ctype_typeId (ct);
6268 if (usymId_equal (iid, uid))
6270 llcontbug (message ("uentry_getRealType: recursive type! %s",
6271 ctype_unparse (ct)));
6276 /* evs 2000-07-25: possible infinite recursion ? */
6277 uentry ue2 = usymtab_getTypeEntry (iid);
6281 llcontbug (message ("Bad recursion: %q", uentry_unparseFull (e)));
6282 return ctype_unknown;
6285 return uentry_getRealType (ue2);
6294 ctype uentry_getForceRealType (uentry e)
6297 typeId uid = USYMIDINVALID;
6299 if (uentry_isInvalid (e))
6301 return ctype_unknown;
6304 llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e)));
6306 if (uentry_isAnyTag (e))
6311 if (uentry_isAbstractType (e))
6313 ct = uentry_getAbstractType (e);
6314 llassert (ctype_isUA (ct));
6316 uid = ctype_typeId (ct);
6317 /* no check for access! */
6320 ct = uentry_getType (e);
6322 /* evs 2000-07-25 */
6323 /* if (ctype_isUserBool (ct)) return ct; */
6325 if (ctype_isManifestBool (ct)) {
6329 if (ctype_isUA (ct))
6331 usymId iid = ctype_typeId (ct);
6333 if (usymId_equal (iid, uid))
6335 llcontbug (message ("uentry_getRealType: recursive type! %s",
6336 ctype_unparse (ct)));
6341 return uentry_getForceRealType (usymtab_getTypeEntry (iid));
6350 uentry uentry_nameCopy (cstring name, uentry e)
6352 uentry enew = uentry_alloc ();
6354 llassert (uentry_isValid (e));
6356 /* enew->shallowCopy = FALSE; */
6357 enew->ukind = e->ukind;
6359 enew->utype = e->utype;
6360 enew->whereSpecified = fileloc_copy (e->whereSpecified);
6361 enew->whereDefined = fileloc_copy (e->whereDefined);
6362 enew->whereDeclared = fileloc_copy (e->whereDeclared);
6363 enew->sref = sRef_copy (e->sref);
6364 enew->used = e->used;
6366 enew->isPrivate = e->isPrivate;
6367 enew->hasNameError = FALSE;
6369 enew->uses = filelocList_new ();
6370 enew->warn = warnClause_undefined;
6372 enew->storageclass = e->storageclass;
6373 enew->info = uinfo_copy (e->info, e->ukind);
6379 uentry_setDatatype (uentry e, usymId uid)
6381 llassert (uentry_isDatatype (e));
6383 if (uentry_isAbstractType (e))
6385 e->info->datatype->type = ctype_createAbstract (uid);
6389 e->info->datatype->type = ctype_createUser (uid);
6394 uentry_setSpecDef (/*@special@*/ uentry e, /*@keep@*/ fileloc f)
6395 /*@defines e->whereSpecified, e->whereDeclared, e->whereDefined@*/
6398 llassert (uentry_isValid (e));
6400 if (fileloc_isSpec (f) || fileloc_isImport (f))
6402 e->whereSpecified = f;
6403 e->whereDeclared = fileloc_undefined;
6404 e->whereDefined = fileloc_undefined;
6408 e->whereSpecified = fileloc_undefined;
6409 e->whereDeclared = f;
6410 e->whereDefined = fileloc_undefined;
6415 ucinfo_free (/*@only@*/ ucinfo u)
6417 multiVal_free (u->val);
6422 uvinfo_free (/*@only@*/ uvinfo u)
6424 /*drl7x added 6/29/01 */
6425 /*free null terminated stuff */
6427 // free(u->bufinfo);
6432 udinfo_free (/*@only@*/ udinfo u)
6438 ufinfo_free (/*@only@*/ ufinfo u)
6440 globSet_free (u->globs);
6441 sRefSet_free (u->mods);
6442 stateClauseList_free (u->specclauses);
6447 uiinfo_free (/*@only@*/ uiinfo u)
6453 ueinfo_free (/*@only@*/ ueinfo u)
6458 static /*@only@*/ ucinfo
6459 ucinfo_copy (ucinfo u)
6461 ucinfo ret = (ucinfo) dmalloc (sizeof (*ret));
6463 ret->val = multiVal_copy (u->val);
6464 ret->access = u->access;
6469 static /*@only@*/ uvinfo
6470 uvinfo_copy (uvinfo u)
6472 uvinfo ret = (uvinfo) dmalloc (sizeof (*ret));
6474 ret->kind = u->kind;
6475 ret->nullstate = u->nullstate;
6476 ret->defstate = u->defstate;
6477 ret->checked = u->checked;
6479 /* drl added 07-02-001 */
6480 /* copy null terminated information */
6482 if (u->bufinfo != NULL)
6484 ret->bufinfo = (bbufinfo) dmalloc (sizeof( * u->bufinfo ) );
6485 ret->bufinfo->bufstate = u->bufinfo->bufstate;
6486 ret->bufinfo->size = u->bufinfo->size;
6487 ret->bufinfo->len = u->bufinfo->len;
6492 ret->bufinfo = NULL;
6498 static /*@only@*/ udinfo
6499 udinfo_copy (udinfo u)
6501 udinfo ret = (udinfo) dmalloc (sizeof (*ret));
6505 ret->type = u->type;
6510 static /*@only@*/ ufinfo
6511 ufinfo_copy (ufinfo u)
6513 ufinfo ret = (ufinfo) dmalloc (sizeof (*ret));
6515 ret->hasGlobs = u->hasGlobs;
6516 ret->hasMods = u->hasMods;
6517 ret->exitCode = u->exitCode;
6518 ret->specialCode = u->specialCode;
6519 ret->nullPred = u->nullPred;
6520 ret->access = u->access;
6521 ret->globs = globSet_newCopy (u->globs);
6522 ret->mods = sRefSet_newCopy (u->mods);
6523 ret->defparams = u->defparams;
6524 ret->specclauses = stateClauseList_copy (u->specclauses);
6526 ret->preconditions = functionConstraint_copy (u->preconditions);
6527 ret->postconditions = functionConstraint_copy (u->postconditions);
6532 static /*@only@*/ uiinfo
6533 uiinfo_copy (uiinfo u)
6535 uiinfo ret = (uiinfo) dmalloc (sizeof (*ret));
6537 ret->access = u->access;
6538 ret->globs = globSet_newCopy (u->globs);
6539 ret->mods = sRefSet_newCopy (u->mods);
6544 static /*@only@*/ ueinfo
6545 ueinfo_copy (ueinfo u)
6547 ueinfo ret = (ueinfo) dmalloc (sizeof (*ret));
6549 ret->access = u->access;
6554 uinfo_free (uinfo u, ekind kind)
6559 case KCONST: ucinfo_free (u->uconst); break;
6560 case KVAR: uvinfo_free (u->var); break;
6564 case KDATATYPE: udinfo_free (u->datatype); break;
6565 case KFCN: ufinfo_free (u->fcn); break;
6566 case KITER: uiinfo_free (u->iter); break;
6567 case KENDITER: ueinfo_free (u->enditer); break;
6568 case KELIPSMARKER: break;
6569 case KINVALID: break;
6575 static /*@only@*/ /*@null@*/ uinfo
6576 uinfo_copy (uinfo u, ekind kind)
6578 if (kind == KELIPSMARKER || kind == KINVALID)
6584 uinfo ret = (uinfo) dmalloc (sizeof (*ret));
6589 case KCONST: ret->uconst = ucinfo_copy (u->uconst); break;
6590 case KVAR: ret->var = uvinfo_copy (u->var); break;
6594 case KDATATYPE: ret->datatype = udinfo_copy (u->datatype); break;
6595 case KFCN: ret->fcn = ufinfo_copy (u->fcn); break;
6596 case KITER: ret->iter = uiinfo_copy (u->iter); break;
6597 case KENDITER: ret->enditer = ueinfo_copy (u->enditer); break;
6605 uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry e)
6607 filelocList_free (e->uses);
6608 cstring_free (e->uname);
6610 uinfo_free (e->info, e->ukind);
6612 fileloc_free (e->whereSpecified);
6613 fileloc_free (e->whereDefined);
6614 fileloc_free (e->whereDeclared);
6616 warnClause_free (e->warn);
6622 extern void uentry_markOwned (/*@owned@*/ uentry u)
6624 sfreeEventually (u);
6628 uentry_free (/*@only@*/ uentry e)
6630 if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
6632 uentry_reallyFree (e);
6637 ** For uentry's in the global or file scope
6641 uentry_freeComplete (/*@only@*/ uentry e)
6643 if (uentry_isValid (e) && !uentry_isElipsisMarker (e))
6645 DPRINTF (("Free complete: %s", sRef_unparseFull (e->sref)));
6646 /*@i@*/ sRef_free (e->sref);
6647 e->sref = sRef_undefined;
6648 uentry_reallyFree (e);
6653 ** requires old->kind != new->kind, old->uname = new->uname
6657 KindConformanceError (/*@unique@*/ uentry old, uentry unew, bool mustConform)
6659 llassert (uentry_isValid (old));
6660 llassert (uentry_isValid (unew));
6662 if (uentry_isEitherConstant (unew)
6663 && (fileloc_isPreproc (uentry_whereDeclared (old))
6664 || ctype_isUnknown (old->utype))
6665 && !uentry_isSpecified (old))
6673 if (!uentry_isDeclared (old))
6675 if (uentry_isSpecified (old))
6677 if (uentry_isSpecified (unew))
6679 llbuglit ("Respecification!");
6681 else if (uentry_isDeclared (unew))
6685 message ("%s %q inconsistently declared as %s: %t",
6686 ekind_capName (old->ukind),
6687 uentry_getName (unew),
6688 ekind_unparseLong (unew->ukind),
6690 uentry_whereDeclared (unew)))
6692 uentry_showWhereLast (old);
6704 message ("%s %q inconsistently declared as %s: %t",
6705 ekind_capName (old->ukind),
6706 uentry_getName (unew),
6707 ekind_unparseLong (unew->ukind),
6709 uentry_whereDeclared (unew)))
6711 uentry_showWhereLast (old);
6717 llassert (uentry_isDeclared (unew));
6721 message ("%s %q inconsistently redeclared as %s",
6722 ekind_capName (old->ukind),
6723 uentry_getName (unew),
6724 ekind_unparseLong (unew->ukind)),
6725 uentry_whereDeclared (unew)))
6727 uentry_showWhereLast (old);
6733 uentry_copyInto (old, unew);
6737 ** def is the definition of spec, modifies spec
6739 ** reports any inconsistencies
6740 ** returns the summary of all available information
6741 ** if spec and def are inconsistent, def is returned
6745 uentry_showWhereLast (uentry spec)
6747 if (uentry_isValid (spec))
6749 if (fileloc_isDefined (spec->whereDefined)
6750 && !fileloc_isLib (spec->whereDefined)
6751 && !fileloc_isPreproc (spec->whereDefined))
6753 llgenindentmsg (message ("Previous definition of %q: %t",
6754 uentry_getName (spec),
6755 uentry_getType (spec)),
6756 uentry_whereDefined (spec));
6758 else if (uentry_isDeclared (spec))
6760 llgenindentmsg (message ("Previous declaration of %q: %t",
6761 uentry_getName (spec),
6762 uentry_getType (spec)),
6763 uentry_whereDeclared (spec));
6765 else if (uentry_isSpecified (spec))
6767 if (uentry_hasName (spec))
6769 llgenindentmsg (message ("Specification of %q: %t",
6770 uentry_getName (spec),
6771 uentry_getType (spec)),
6772 uentry_whereSpecified (spec));
6776 llgenindentmsg (message ("Specification: %t", uentry_getType (spec)),
6777 uentry_whereSpecified (spec));
6782 /* nothing to show */
6788 uentry_showDefSpecInfo (uentry ce, fileloc fwhere)
6790 fileloc loc = uentry_whereDefined (ce);
6792 if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
6794 llgenindentmsg (message ("Definition of %q", uentry_getName (ce)),
6798 loc = uentry_whereSpecified (ce);
6800 if (fileloc_isUser (loc) && !fileloc_equal (loc, fwhere))
6802 llgenindentmsg (message ("Specification of %q", uentry_getName (ce)),
6807 void uentry_showWhereLastExtra (uentry spec, cstring extra)
6809 if (uentry_isDeclared (spec))
6811 llgenindentmsg (message ("Previous declaration of %q: %q",
6812 uentry_getName (spec), extra),
6813 uentry_whereDeclared (spec));
6815 else if (uentry_isSpecified (spec))
6817 llgenindentmsg (message ("Specification of %q: %q",
6818 uentry_getName (spec), extra),
6819 uentry_whereSpecified (spec));
6823 cstring_free (extra);
6828 uentry_showWhereDeclared (uentry spec)
6830 if (uentry_isDeclared (spec))
6832 if (uentry_hasName (spec))
6834 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
6835 uentry_whereDeclared (spec));
6839 llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
6842 else if (uentry_isSpecified (spec))
6844 if (uentry_hasName (spec))
6846 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
6847 uentry_whereSpecified (spec));
6851 llgenindentmsg (cstring_makeLiteral ("Specification"), uentry_whereSpecified (spec));
6856 /* nothing to show */
6862 uentry_showWhereAny (uentry spec)
6864 if (uentry_isDeclared (spec))
6866 if (uentry_hasName (spec))
6868 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
6869 uentry_whereDeclared (spec));
6873 llgenindentmsg (cstring_makeLiteral ("Declaration"), uentry_whereDeclared (spec));
6876 else if (uentry_isSpecified (spec))
6878 if (uentry_hasName (spec))
6880 llgenindentmsg (message ("Specification of %q",
6881 uentry_getName (spec)),
6882 uentry_whereSpecified (spec));
6886 llgenindentmsg (cstring_makeLiteral ("Specification"),
6887 uentry_whereSpecified (spec));
6890 else if (fileloc_isDefined (uentry_whereDefined (spec)))
6892 if (uentry_hasName (spec))
6894 llgenindentmsg (message ("Definition of %q", uentry_getName (spec)),
6895 uentry_whereDefined (spec));
6899 llgenindentmsg (cstring_makeLiteral ("Definition"), uentry_whereDefined (spec));
6904 /* nothing to show */
6909 uentry_showWhereDefined (uentry spec)
6911 if (uentry_isCodeDefined (spec))
6913 llgenindentmsg (message ("Previous definition of %q", uentry_getName (spec)),
6914 uentry_whereDefined (spec));
6919 uentry_showWhereLastPlain (uentry spec)
6921 if (uentry_isDeclared (spec))
6923 llgenindentmsg (message ("Previous declaration of %q", uentry_getName (spec)),
6924 uentry_whereDeclared (spec));
6926 else if (uentry_isSpecified (spec))
6928 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
6929 uentry_whereSpecified (spec));
6937 uentry_showWhereLastVal (uentry spec, cstring val)
6939 if (uentry_isDeclared (spec))
6941 llgenindentmsg (message ("Previous declaration of %q: %s",
6942 uentry_getName (spec), val),
6943 uentry_whereDeclared (spec));
6945 else if (uentry_isSpecified (spec))
6947 llgenindentmsg (message ("Specification of %q: %s",
6948 uentry_getName (spec), val),
6949 uentry_whereSpecified (spec));
6957 uentry_showWhereSpecified (uentry spec)
6959 if (uentry_isSpecified (spec))
6961 if (uentry_hasName (spec))
6963 llgenindentmsg (message ("Specification of %q", uentry_getName (spec)),
6964 uentry_whereSpecified (spec));
6968 llgenindentmsg (cstring_makeLiteral ("Specification"),
6969 uentry_whereSpecified (spec));
6972 else if (uentry_isDeclared (spec))
6974 llgenindentmsg (message ("Declaration of %q", uentry_getName (spec)),
6975 uentry_whereDeclared (spec));
6979 /* nothing to show */
6984 uentry_showWhereSpecifiedExtra (uentry spec, cstring s)
6986 if (uentry_isSpecified (spec))
6988 if (uentry_hasName (spec))
6990 llgenindentmsg (message ("Specification of %q: %q",
6991 uentry_getName (spec), s),
6992 uentry_whereSpecified (spec));
6996 llgenindentmsg (message ("Specification: %q", s),
6997 uentry_whereSpecified (spec));
7000 else if (uentry_isDeclared (spec))
7002 llgenindentmsg (message ("Declaration of %q: %q",
7003 uentry_getName (spec), s),
7004 uentry_whereDeclared (spec));
7008 llgenindentmsg (message ("Previous: %q", s),
7009 uentry_whereLast (spec));
7018 checkStructConformance (uentry old, uentry unew)
7021 uentryList fold, fnew;
7024 ** requires: types of old and new are structs or unions
7027 llassert (uentry_isValid (old));
7028 llassert (uentry_isValid (unew));
7030 oldr = ctype_realType (old->utype);
7031 fold = ctype_getFields (oldr);
7033 newr = ctype_realType (unew->utype);
7034 fnew = ctype_getFields (newr);
7036 if (!uentryList_matchFields (fold, fnew))
7038 if (fileloc_equal (uentry_whereLast (old),
7039 uentry_whereLast (unew)))
7047 message ("%q %q %rdeclared with fields { %q }, %s "
7048 "with fields { %q }",
7049 cstring_makeLiteral (ctype_isStruct (newr) ? "Structure": "Union"),
7050 uentry_getName (old),
7051 uentry_isDeclared (old),
7052 uentryList_unparseAbbrev (fnew),
7053 uentry_specOrDefName (old),
7054 uentryList_unparseAbbrev (fold)),
7055 uentry_whereDeclared (unew)))
7057 uentry_showWhereLastPlain (old);
7058 uentryList_showFieldDifference (fold, fnew);
7062 old->utype = unew->utype;
7067 checkEnumConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
7070 ** requires old and new are enums
7073 ctype rold = ctype_realType (old->utype);
7074 ctype rnew = ctype_realType (unew->utype);
7075 enumNameList eold = ctype_elist (rold);
7076 enumNameList enew = ctype_elist (rnew);
7078 if (!enumNameList_match (eold, enew))
7082 message ("Enum %q declared with members { %q } but "
7083 "specified with members { %q }",
7084 uentry_getName (old),
7085 enumNameList_unparse (enew),
7086 enumNameList_unparse (eold)),
7087 uentry_whereDeclared (unew)))
7089 uentry_showWhereSpecified (old);
7090 old->utype = unew->utype;
7096 ** either oldCurrent or newCurrent may be undefined!
7100 paramTypeError (uentry old, uentry oldCurrent, ctype oldType,
7101 uentry unew, uentry newCurrent, ctype newType,
7104 bool hasError = FALSE;
7106 if (uentry_isValid (newCurrent) && uentry_isDeclared (newCurrent))
7108 if (uentry_hasName (newCurrent))
7110 hasError = optgenerror
7112 message ("Parameter %d, %q, of function %q has inconsistent type: "
7113 "declared %t, %s %t",
7114 paramno + 1, uentry_getName (newCurrent),
7115 uentry_getName (unew),
7116 newType, uentry_specOrDefName (old), oldType),
7117 uentry_whereDeclared (newCurrent));
7121 hasError = optgenerror
7123 message ("Parameter %d of function %q has inconsistent type: "
7124 "declared %t, %s %t",
7125 paramno + 1, uentry_getName (unew),
7126 newType, uentry_specOrDefName (old), oldType),
7127 uentry_whereDeclared (newCurrent));
7129 DPRINTF (("type: %s / %s",
7130 ctype_unparse (newType),
7131 ctype_unparse (ctype_realType (newType))));
7136 if (uentry_isDeclared (unew))
7138 hasError = optgenerror
7140 message ("Parameter %d of function %s has inconsistent type: "
7141 "declared %t, %s %t",
7142 paramno + 1, unew->uname,
7143 newType, uentry_specOrDefName (old), oldType),
7144 uentry_whereDeclared (unew));
7148 hasError = optgenerror
7150 message ("Parameter %d of function %s has inconsistent type: "
7151 "declared %t, %s %t",
7152 paramno + 1, unew->uname,
7153 newType, uentry_specOrDefName (old), oldType),
7154 uentry_whereDeclared (unew));
7160 if (!uentry_isUndefined (oldCurrent))
7162 if (!uentry_isUndefined (newCurrent)
7163 && cstring_equal (uentry_rawName (newCurrent), uentry_rawName (oldCurrent)))
7165 uentry_showWhereLast (oldCurrent);
7169 uentry_showWhereLastPlain (old);
7172 uentry_setType (oldCurrent, newType);
7176 uentry_showWhereLastPlain (old);
7182 nargsError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
7186 message ("Function %s %rdeclared with %d arg%&, %s with %d",
7188 uentry_isDeclared (old),
7189 uentryList_size (uentry_getParams (unew)),
7190 uentry_specOrDefName (old),
7191 uentryList_size (uentry_getParams (old))),
7192 uentry_whereDeclared (unew)))
7194 uentry_showWhereLastPlain (old);
7199 returnValueError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew)
7203 message ("Function %s inconsistently %rdeclared to return %t",
7205 uentry_isDeclared (old),
7206 ctype_getReturnType (unew->utype)),
7207 uentry_whereDeclared (unew)))
7209 uentry_showWhereLastVal (old, ctype_unparse (ctype_getReturnType (old->utype)));
7213 static cstring paramStorageName (uentry ue)
7215 return (cstring_makeLiteralTemp (uentry_isParam (ue) ? "param" : "storage"));
7218 static cstring fcnErrName (uentry ue)
7220 return (cstring_makeLiteralTemp (uentry_isFunction (ue) ? "to return" : "as"));
7223 extern /*@observer@*/ cstring uentry_checkedName (uentry ue)
7225 if (uentry_isVar (ue))
7227 return (checkedName (ue->info->var->checked));
7231 return (cstring_makeLiteralTemp ("<checked invalid>"));
7235 static cstring checkedName (chkind checked)
7239 case CH_UNKNOWN: return (cstring_makeLiteralTemp ("unknown"));
7240 case CH_UNCHECKED: return (cstring_makeLiteralTemp ("unchecked"));
7241 case CH_CHECKED: return (cstring_makeLiteralTemp ("checked"));
7242 case CH_CHECKMOD: return (cstring_makeLiteralTemp ("checkmod"));
7243 case CH_CHECKEDSTRICT: return (cstring_makeLiteralTemp ("checkedstrict"));
7249 void checkNullState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, bool mustConform, bool completeConform)
7254 if (uentry_isVar (unew))
7256 llassert (uentry_isVar (old));
7258 oldState = old->info->var->nullstate;
7259 newState = unew->info->var->nullstate;
7263 oldState = sRef_getNullState (old->sref);
7264 newState = sRef_getNullState (unew->sref);
7267 if (oldState == NS_ABSNULL)
7269 if (uentry_isVar (old))
7271 old->info->var->nullstate = newState;
7274 sRef_mergeNullState (old->sref, newState);
7276 else if (newState == NS_UNKNOWN)
7278 if (completeConform && newState != oldState
7279 && uentry_isReallySpecified (old))
7283 message ("%s %q specified as %s, but declared without %s qualifier",
7284 ekind_capName (unew->ukind),
7285 uentry_getName (unew),
7286 nstate_unparse (oldState),
7287 nstate_unparse (oldState)),
7288 uentry_whereDeclared (unew)))
7290 uentry_showWhereSpecified (old);
7294 if (uentry_isVar (unew))
7296 unew->info->var->nullstate = oldState;
7299 sRef_mergeNullState (unew->sref, oldState);
7301 else if (newState == NS_POSNULL)
7303 if (oldState == NS_MNOTNULL
7304 && (ctype_isUA (unew->utype)
7305 || (uentry_isFunction (unew)
7306 && ctype_isUA (ctype_getReturnType (unew->utype)))))
7308 if (uentry_isVar (unew))
7310 unew->info->var->nullstate = oldState;
7313 sRef_mergeNullState (unew->sref, oldState);
7317 if (oldState == NS_NOTNULL || oldState == NS_MNOTNULL
7318 || oldState == NS_UNKNOWN)
7325 ("%s %q inconsistently %rdeclared %s possibly null storage, "
7327 uentry_ekindName (unew),
7328 uentry_getName (unew),
7329 uentry_isDeclared (old),
7331 uentry_specOrDefName (old),
7332 cstring_makeLiteral (oldState == NS_MNOTNULL ? "with notnull" : "without null")),
7333 uentry_whereDeclared (unew)))
7335 uentry_showWhereSpecified (old);
7340 if (uentry_isVar (old))
7342 old->info->var->nullstate = newState;
7345 sRef_mergeNullState (old->sref, newState);
7348 else if (newState == NS_MNOTNULL)
7350 if (oldState != NS_MNOTNULL)
7356 message ("%s %q inconsistently %rdeclared %s notnull storage, "
7357 "%s without notnull qualifier",
7358 uentry_ekindName (unew),
7359 uentry_getName (unew),
7360 uentry_isDeclared (old),
7362 uentry_specOrDefName (old)),
7363 uentry_whereDeclared (unew)))
7365 uentry_showWhereSpecified (old);
7369 if (uentry_isVar (old))
7371 old->info->var->nullstate = newState;
7374 sRef_mergeNullState (old->sref, newState);
7379 if (uentry_isVar (unew))
7381 unew->info->var->nullstate = oldState;
7384 sRef_mergeNullState (unew->sref, oldState);
7389 void checkDefState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7390 bool mustConform, bool completeConform)
7396 if (uentry_isVar (old) && uentry_isVar (unew))
7398 oldState = old->info->var->defstate;
7399 newState = unew->info->var->defstate;
7404 oldState = sRef_getDefState (old->sref);
7405 newState = sRef_getDefState (unew->sref);
7408 if (newState != oldState
7409 && newState != SS_UNKNOWN
7410 && newState != SS_DEFINED)
7412 DPRINTF (("Where declared: %s / %s",
7413 fileloc_unparse (uentry_whereDeclared (unew)),
7414 bool_unparse (fileloc_isXHFile (uentry_whereDeclared (unew)))));
7420 message ("%s %q inconsistently %rdeclared %s %s %s, "
7422 uentry_ekindName (unew),
7423 uentry_getName (unew),
7424 uentry_isDeclared (old),
7426 sstate_unparse (newState),
7427 paramStorageName (unew),
7428 uentry_specOrDefName (old),
7430 sstate_unparse (oldState),
7431 paramStorageName (unew)),
7432 uentry_whereDeclared (unew)))
7434 uentry_showWhereSpecified (old);
7438 if (vars) old->info->var->defstate = newState;
7439 sRef_setDefState (old->sref, newState, uentry_whereDeclared (unew));
7444 && (newState != oldState) && (oldState != SS_DEFINED)
7445 && uentry_isReallySpecified (old))
7449 message ("%s %q specified as %s, but declared without %s qualifier",
7450 ekind_capName (unew->ukind),
7451 uentry_getName (unew),
7452 sstate_unparse (oldState),
7453 sstate_unparse (oldState)),
7454 uentry_whereDeclared (unew)))
7456 uentry_showWhereSpecified (old);
7460 if (vars) unew->info->var->defstate = oldState;
7461 sRef_setDefState (unew->sref, oldState, uentry_whereDeclared (unew));
7466 checkAliasState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7467 bool mustConform, bool completeConform)
7472 oldKind = sRef_getAliasKind (old->sref);
7473 newKind = sRef_getAliasKind (unew->sref);
7475 if (alkind_isImplicit (newKind)
7476 || (alkind_isRefCounted (newKind) && !uentry_isDatatype (unew)))
7478 if (completeConform && !alkind_equal (newKind, oldKind)
7479 && uentry_isReallySpecified (old))
7483 message ("%s %q specified as %s, but declared without "
7484 "explicit alias qualifier",
7485 ekind_capName (unew->ukind),
7486 uentry_getName (unew),
7487 alkind_unparse (oldKind)),
7488 uentry_whereDeclared (unew)))
7490 uentry_showWhereSpecified (old);
7495 ** This really shouldn't be necessary, but it is!
7496 ** Function params (?) use new here.
7499 sRef_setAliasKind (unew->sref, oldKind, uentry_whereDeclared (unew));
7503 if (alkind_isKnown (newKind))
7505 if (!alkind_equal (oldKind, newKind))
7507 if (alkind_isKnown (oldKind))
7512 message ("%s %q inconsistently %rdeclared %s %s storage, "
7514 uentry_ekindName (unew),
7515 uentry_getName (unew),
7516 uentry_isDeclared (old),
7518 alkind_unparse (newKind),
7519 uentry_specOrDefName (old),
7520 alkind_unparse (oldKind)),
7521 uentry_whereDeclared (unew)))
7523 uentry_showWhereSpecified (old);
7525 DPRINTF (("Old: %s", sRef_unparseFull (old->sref)));
7526 DPRINTF (("New: %s", sRef_unparseFull (unew->sref)));
7527 sRef_setAliasKind (old->sref, AK_ERROR,
7528 uentry_whereDeclared (unew));
7532 sRef_setAliasKind (old->sref, newKind,
7533 uentry_whereDeclared (unew));
7538 if (!(alkind_isImplicit (newKind)))
7541 !uentry_isFunction (unew) &&
7544 message ("%s %q inconsistently %rdeclared %s %s storage, "
7545 "implicitly %s as temp storage",
7546 uentry_ekindName (unew),
7547 uentry_getName (unew),
7548 uentry_isDeclared (old),
7550 alkind_unparse (newKind),
7551 uentry_specOrDefName (old)),
7552 uentry_whereDeclared (unew)))
7554 uentry_showWhereSpecified (old);
7558 sRef_setAliasKind (old->sref, newKind,
7559 uentry_whereDeclared (unew));
7561 else /* newKind is temp or refcounted */
7568 else /* newKind unknown */
7575 checkExpState(/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7576 bool mustConform, bool completeConform)
7581 oldKind = sRef_getExKind (old->sref);
7582 newKind = sRef_getExKind (unew->sref);
7584 if (exkind_isKnown (newKind))
7586 if (oldKind != newKind)
7588 if (exkind_isKnown (oldKind))
7593 message ("%s %q inconsistently %rdeclared %s %s, %s as %s",
7594 uentry_ekindName (unew),
7595 uentry_getName (unew),
7596 uentry_isDeclared (old),
7598 exkind_unparse (newKind),
7599 uentry_specOrDefName (old),
7600 exkind_unparse (oldKind)),
7601 uentry_whereDeclared (unew)))
7603 uentry_showWhereSpecified (old);
7606 sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
7613 message ("%s %q inconsistently %rdeclared %s %s, "
7614 "implicitly %s without exposure qualifier",
7615 uentry_ekindName (unew),
7616 uentry_getName (unew),
7617 uentry_isDeclared (old),
7619 exkind_unparse (newKind),
7620 uentry_specOrDefName (old)),
7621 uentry_whereDeclared (unew)))
7623 uentry_showWhereSpecified (old);
7626 sRef_setExKind (old->sref, newKind, uentry_whereDefined (unew));
7632 if (completeConform && exkind_isKnown (oldKind)
7633 && uentry_isReallySpecified (old))
7637 message ("%s %q specified as %s, but declared without "
7638 "exposure qualifier",
7639 ekind_capName (unew->ukind),
7640 uentry_getName (unew),
7641 exkind_unparse (oldKind)),
7642 uentry_whereDeclared (unew)))
7644 uentry_showWhereSpecified (old);
7648 /* yes, this is necessary! (if its a param) */
7649 sRef_setExKind (unew->sref, oldKind, fileloc_undefined);
7654 checkMetaState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
7655 bool mustConform, /*@unused@*/ bool completeConform)
7657 valueTable newvals = sRef_getValueTable (unew->sref);
7659 if (valueTable_isDefined (newvals))
7661 DPRINTF (("Check meta state: %s -> %s",
7662 uentry_unparseFull (old),
7663 uentry_unparseFull (unew)));
7665 DPRINTF (("Check meta state refs: %s -> %s",
7666 sRef_unparseFull (old->sref),
7667 sRef_unparseFull (unew->sref)));
7669 DPRINTF (("Value table: %s", valueTable_unparse (newvals)));
7672 ** Copy the new values into the old ref
7675 valueTable_elements (newvals, key, newval)
7677 metaStateInfo msinfo = context_lookupMetaStateInfo (key);
7678 stateValue oldval = sRef_getMetaStateValue (old->sref, key);
7680 llassert (metaStateInfo_isDefined (msinfo));
7682 if (stateValue_isUndefined (oldval))
7684 sRef_setMetaStateValue (old->sref, key, stateValue_getValue (newval), uentry_whereLast (unew));
7688 if (stateValue_isError (oldval))
7690 if (!stateValue_isError (newval))
7692 sRef_setMetaStateValue (old->sref, key, stateValue_getValue (newval), uentry_whereLast (unew));
7696 ; /* No change necessary. */
7701 if (stateValue_getValue (newval) != stateValue_getValue (oldval))
7703 if (fileloc_isXHFile (uentry_whereDeclared (unew)))
7709 if (!stateValue_isError (newval))
7714 message ("%s %q inconsistently %rdeclared %s %s, %s as %s",
7715 uentry_ekindName (unew),
7716 uentry_getName (unew),
7717 uentry_isDeclared (old),
7719 metaStateInfo_unparseValue (msinfo,
7720 stateValue_getValue (newval)),
7721 uentry_specOrDefName (old),
7722 metaStateInfo_unparseValue (msinfo,
7723 stateValue_getValue (oldval))),
7724 uentry_whereDeclared (unew)))
7726 uentry_showWhereSpecified (old);
7731 DPRINTF (("Updating!"));
7732 sRef_setMetaStateValue (old->sref, key, stateValue_getValue (newval), uentry_whereLast (unew));
7736 DPRINTF (("Values match"));
7740 } end_valueTable_elements ;
7745 uentry_checkStateConformance (/*@notnull@*/ uentry old,
7746 /*@notnull@*/ uentry unew,
7747 bool mustConform, bool completeConform)
7749 checkDefState (old, unew, mustConform, completeConform);
7750 checkNullState (old, unew, mustConform, completeConform);
7751 checkAliasState (old, unew, mustConform, completeConform);
7752 checkExpState (old, unew, mustConform, completeConform);
7753 checkMetaState (old, unew, mustConform, completeConform);
7755 sRef_storeState (old->sref);
7756 sRef_storeState (unew->sref);
7760 checkVarConformance (uentry old, uentry unew, bool mustConform, bool completeConform)
7762 if (uentry_isElipsisMarker (old) || uentry_isElipsisMarker (unew))
7767 llassert (uentry_isVar (old));
7768 llassert (uentry_isVar (unew));
7770 if (cstring_isEmpty (old->uname))
7772 cstring_free (old->uname);
7773 old->uname = cstring_copy (unew->uname);
7776 if (unew->info->var->kind == VKRETPARAM
7777 || unew->info->var->kind == VKSEFRETPARAM)
7779 if (old->info->var->kind != VKRETPARAM
7780 && old->info->var->kind != VKSEFRETPARAM)
7784 message ("Parameter %q inconsistently %rdeclared as "
7785 "returned parameter",
7786 uentry_getName (unew),
7787 uentry_isDeclared (old)),
7788 uentry_whereDeclared (unew)))
7790 uentry_showWhereSpecified (old);
7791 old->info->var->kind = unew->info->var->kind;
7797 if (unew->info->var->kind == VKSEFPARAM || unew->info->var->kind == VKSEFRETPARAM)
7799 if (old->info->var->kind != VKSEFPARAM
7800 && old->info->var->kind != VKSEFRETPARAM)
7804 message ("Parameter %qinconsistently %rdeclared as "
7806 uentry_getOptName (unew),
7807 uentry_isDeclared (old)),
7808 uentry_whereDeclared (unew)))
7810 uentry_showWhereSpecified (old);
7811 old->info->var->kind = unew->info->var->kind;
7816 if (old->info->var->kind == VKSPEC)
7818 old->info->var->kind = unew->info->var->kind;
7822 unew->info->var->kind = old->info->var->kind;
7825 if (unew->info->var->checked != CH_UNKNOWN
7826 && unew->info->var->checked != old->info->var->checked)
7828 if (old->info->var->checked == CH_UNKNOWN
7829 && !fileloc_isUser (uentry_whereLast (old)))
7837 message ("Variable %q inconsistently %rdeclared as "
7838 "%s parameter (was %s)",
7839 uentry_getName (unew),
7840 uentry_isDeclared (old),
7841 checkedName (unew->info->var->checked),
7842 checkedName (old->info->var->checked)),
7843 uentry_whereDeclared (unew)))
7845 uentry_showWhereSpecified (old);
7849 old->info->var->checked = unew->info->var->checked;
7854 && (old->info->var->checked != CH_UNKNOWN)
7855 && uentry_isReallySpecified (old))
7859 message ("%s %q specified as %s, but declared without %s qualifier",
7860 ekind_capName (unew->ukind),
7861 uentry_getName (unew),
7862 checkedName (old->info->var->checked),
7863 checkedName (old->info->var->checked)),
7864 uentry_whereDeclared (unew)))
7866 uentry_showWhereSpecified (old);
7870 unew->info->var->checked = old->info->var->checked;
7873 uentry_checkStateConformance (old, unew, mustConform, completeConform);
7876 void uentry_checkMatchParam (uentry u1, uentry u2, int paramno, exprNode e)
7878 if (uentry_isElipsisMarker (u1) || uentry_isElipsisMarker (u2))
7883 llassert (uentry_isVar (u1));
7884 llassert (uentry_isVar (u2));
7886 if (u1->info->var->kind != u2->info->var->kind) {
7887 if (u1->info->var->kind == VKSEFRETPARAM) {
7888 if (u2->info->var->kind == VKRETPARAM) {
7891 message ("Function types are inconsistent. Parameter %d is "
7892 "sef parameter, but non-sef parameter in "
7893 "assigned function: %s",
7894 paramno, exprNode_unparse (e)),
7896 } else if (u2->info->var->kind == VKSEFPARAM) {
7899 message ("Function types are inconsistent. Parameter %d is "
7900 "returns parameter, but non-returns parameter in "
7901 "assigned function: %s",
7902 paramno, exprNode_unparse (e)),
7907 message ("Function types are inconsistent. Parameter %d is "
7908 "sef returns parameter, but non-sef returns parameter in "
7909 "assigned function: %s",
7910 paramno, exprNode_unparse (e)),
7913 } else if (u1->info->var->kind == VKRETPARAM) {
7916 message ("Function types are inconsistent. Parameter %d is "
7917 "returns parameter, but non-returns parameter in "
7918 "assigned function: %s",
7919 paramno, exprNode_unparse (e)),
7921 } else if (u1->info->var->kind == VKSEFPARAM) {
7924 message ("Function types are inconsistent. Parameter %d is "
7925 "sef parameter, but non-sef parameter in "
7926 "assigned function: %s",
7927 paramno, exprNode_unparse (e)),
7930 if (u2->info->var->kind == VKSEFRETPARAM) {
7933 message ("Function types are inconsistent. Parameter %d is "
7934 "normal parameter, but sef returns parameter in "
7935 "assigned function: %s",
7936 paramno, exprNode_unparse (e)),
7938 } else if (u2->info->var->kind == VKSEFPARAM) {
7941 message ("Function types are inconsistent. Parameter %d is "
7942 "normal parameter, but sef parameter in "
7943 "assigned function: %s",
7944 paramno, exprNode_unparse (e)),
7946 } else if (u2->info->var->kind == VKRETPARAM) {
7949 message ("Function types are inconsistent. Parameter %d is "
7950 "normal parameter, but returns parameter in "
7951 "assigned function: %s",
7952 paramno, exprNode_unparse (e)),
7960 if (u1->info->var->defstate != u2->info->var->defstate)
7964 message ("Function types are inconsistent. Parameter %d is "
7965 "%s, but %s in assigned function: %s",
7967 sstate_unparse (u1->info->var->defstate),
7968 sstate_unparse (u2->info->var->defstate),
7969 exprNode_unparse (e)),
7973 if (u1->info->var->nullstate != u2->info->var->nullstate)
7977 message ("Function types are inconsistent. Parameter %d is "
7978 "%s, but %s in assigned function: %s",
7980 nstate_unparse (u1->info->var->nullstate),
7981 nstate_unparse (u2->info->var->nullstate),
7982 exprNode_unparse (e)),
7986 if (sRef_getAliasKind (u1->sref) != sRef_getAliasKind (u2->sref))
7990 message ("Function types are inconsistent. Parameter %d is "
7991 "%s, but %s in assigned function: %s",
7993 alkind_unparse (sRef_getAliasKind (u1->sref)),
7994 alkind_unparse (sRef_getAliasKind (u2->sref)),
7995 exprNode_unparse (e)),
7999 if (sRef_getExKind (u1->sref) != sRef_getExKind (u2->sref))
8003 message ("Function types are inconsistent. Parameter %d is "
8004 "%s, but %s in assigned function: %s",
8006 exkind_unparse (sRef_getExKind (u1->sref)),
8007 exkind_unparse (sRef_getExKind (u2->sref)),
8008 exprNode_unparse (e)),
8014 checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old,
8015 /*@notnull@*/ uentry unew,
8016 bool mustConform, /*@unused@*/ bool completeConform)
8018 uentryList oldParams = uentry_getParams (old);
8019 uentryList newParams = uentry_getParams (unew);
8020 ctype newType = unew->utype;
8021 ctype oldType = old->utype;
8022 ctype oldRetType = ctype_unknown;
8023 ctype newRetType = ctype_unknown;
8025 DPRINTF (("Function conform: %s ==> %s",
8026 uentry_unparseFull (old),
8027 uentry_unparseFull (unew)));
8029 if (uentry_isForward (old))
8031 mustConform = FALSE;
8032 uentry_copyInto (old, unew);
8037 ** check return values
8040 if (ctype_isKnown (oldType))
8042 llassert (ctype_isFunction (oldType));
8044 oldRetType = ctype_getReturnType (oldType);
8047 if (ctype_isKnown (newType))
8049 llassert (ctype_isFunction (newType));
8051 newRetType = ctype_getReturnType (newType);
8054 if (ctype_isKnown (oldRetType) && ctype_isKnown (newRetType)
8055 && !ctype_matchDef (newRetType, oldRetType))
8057 if (mustConform) returnValueError (old, unew);
8061 if (ctype_isConj (newRetType))
8063 if (ctype_isConj (oldRetType))
8065 if (!ctype_sameAltTypes (newRetType, oldRetType))
8069 message ("Function %q inconsistently %rdeclared to "
8070 "return alternate types %s "
8071 "(types match, but alternates are not identical, "
8072 "so checking may not be correct)",
8073 uentry_getName (unew),
8074 uentry_isDeclared (old),
8075 ctype_unparse (newRetType)),
8076 uentry_whereDeclared (unew)))
8078 uentry_showWhereLastVal (old, ctype_unparse (oldRetType));
8084 old->utype = ctype_makeFunction (oldRetType, uentryList_copy (newParams));
8089 DPRINTF (("Before state: %s",
8090 uentry_unparseFull (old)));
8091 uentry_checkStateConformance (old, unew, mustConform, completeConform);
8092 DPRINTF (("After state: %s",
8093 uentry_unparseFull (old)));
8095 if (!exitkind_equal (unew->info->fcn->exitCode, old->info->fcn->exitCode))
8097 if (exitkind_isKnown (unew->info->fcn->exitCode))
8101 message ("Function %q inconsistently %rdeclared using %s",
8102 uentry_getName (unew),
8103 uentry_isDeclared (old),
8104 exitkind_unparse (unew->info->fcn->exitCode)),
8105 uentry_whereDeclared (unew)))
8107 uentry_showWhereSpecified (old);
8112 unew->info->fcn->exitCode = old->info->fcn->exitCode;
8116 if (!qual_isUnknown (unew->info->fcn->nullPred))
8118 if (!qual_match (old->info->fcn->nullPred, unew->info->fcn->nullPred))
8122 message ("Function %q inconsistently %rdeclared using %s",
8123 uentry_getName (unew),
8124 uentry_isDeclared (old),
8125 qual_unparse (unew->info->fcn->nullPred)),
8126 uentry_whereDeclared (unew)))
8128 uentry_showWhereSpecified (old);
8134 unew->info->fcn->nullPred = old->info->fcn->nullPred;
8137 if (unew->info->fcn->specialCode != SPC_NONE)
8139 if (old->info->fcn->specialCode != unew->info->fcn->specialCode)
8143 message ("Function %q inconsistently %rdeclared using %s",
8144 uentry_getName (unew),
8145 uentry_isDeclared (old),
8146 specCode_unparse (unew->info->fcn->specialCode)),
8147 uentry_whereDeclared (unew)))
8149 uentry_showWhereSpecified (old);
8155 unew->info->fcn->specialCode = old->info->fcn->specialCode;
8162 if (!uentryList_sameObject (oldParams, newParams)
8163 && (!uentryList_isMissingParams (oldParams)))
8165 if (!uentryList_isMissingParams (newParams))
8168 int nparams = uentryList_size (oldParams);
8169 bool checknames = context_maybeSet (FLG_DECLPARAMMATCH);
8171 if (nparams != uentryList_size (newParams))
8173 nargsError (old, unew);
8176 if (uentryList_size (newParams) < nparams)
8178 nparams = uentryList_size (newParams);
8181 while (paramno < nparams)
8183 uentry oldCurrent = uentryList_getN (oldParams, paramno);
8184 uentry newCurrent = uentryList_getN (newParams, paramno);
8185 ctype oldCurrentType = uentry_getType (oldCurrent);
8186 ctype newCurrentType = uentry_getType (newCurrent);
8188 llassert (uentry_isValid (oldCurrent)
8189 && uentry_isValid (newCurrent));
8191 if (!uentry_isElipsisMarker (oldCurrent)
8192 && !uentry_isElipsisMarker (newCurrent))
8194 checkVarConformance (oldCurrent, newCurrent,
8195 mustConform, completeConform);
8200 if (uentry_hasName (oldCurrent)
8201 && uentry_hasName (newCurrent))
8203 cstring oldname = uentry_getName (oldCurrent);
8204 cstring pfx = context_getString (FLG_DECLPARAMPREFIX);
8206 cstring nname = uentry_getName (newCurrent);
8209 if (cstring_isDefined (pfx)
8210 && cstring_equalPrefix (oldname, cstring_toCharsSafe (pfx)))
8212 oname = cstring_suffix (oldname, cstring_length (pfx));
8217 /*@-branchstate@*/ } /*@=branchstate@*/
8219 if (cstring_isDefined (pfx)
8220 && cstring_equalPrefix (nname, cstring_toCharsSafe (pfx)))
8222 nnamefix = cstring_suffix (nname, cstring_length (pfx));
8227 /*@-branchstate@*/ } /*@=branchstate@*/
8229 if (!cstring_equal (oname, nnamefix))
8232 (FLG_DECLPARAMMATCH,
8233 message ("Definition parameter name %s does not match "
8234 "name of corresponding parameter in "
8237 uentry_whereLast (newCurrent)))
8239 uentry_showWhereLastPlain (oldCurrent);
8243 cstring_free (oldname);
8244 cstring_free (nname);
8248 if (!ctype_match (oldCurrentType, newCurrentType))
8250 paramTypeError (old, oldCurrent, oldCurrentType,
8251 unew, newCurrent, newCurrentType, paramno);
8255 if (ctype_isMissingParamsMarker (newCurrentType)
8256 || ctype_isElips (newCurrentType)
8257 || ctype_isMissingParamsMarker (oldCurrentType)
8258 || ctype_isElips (oldCurrentType))
8264 if (ctype_isConj (newCurrentType))
8266 if (ctype_isConj (oldCurrentType))
8268 if (!ctype_sameAltTypes (newCurrentType, oldCurrentType))
8272 message ("Parameter %q inconsistently %rdeclared with "
8273 "alternate types %s "
8274 "(types match, but alternates are not identical, "
8275 "so checking may not be correct)",
8276 uentry_getName (newCurrent),
8277 uentry_isDeclared (oldCurrent),
8278 ctype_unparse (newCurrentType)),
8279 uentry_whereDeclared (unew)))
8281 uentry_showWhereLastVal (oldCurrent,
8282 ctype_unparse (oldCurrentType));
8290 message ("Parameter %q inconsistently %rdeclared with "
8291 "alternate types %s",
8292 uentry_getName (newCurrent),
8293 uentry_isDeclared (oldCurrent),
8294 ctype_unparse (newCurrentType)),
8295 uentry_whereDeclared (unew)))
8297 uentry_showWhereLastVal (oldCurrent,
8298 ctype_unparse (oldCurrentType));
8305 if (ctype_isConj (oldCurrentType))
8307 uentry_setType (newCurrent, oldCurrentType);
8315 ** Forgot this! detected by lclint:
8316 ** uentry.c:1257,15: Suspected infinite loop
8322 if (!uentryList_isMissingParams (newParams))
8324 if (ctype_isConj (oldRetType))
8326 old->utype = ctype_makeFunction (oldRetType,
8327 uentryList_copy (newParams));
8331 old->utype = unew->utype;
8335 checkGlobalsConformance (old, unew, mustConform, completeConform);
8336 checkModifiesConformance (old, unew, mustConform, completeConform);
8338 DPRINTF (("Before list: %s",
8339 uentry_unparseFull (old)));
8341 if (stateClauseList_isDefined (unew->info->fcn->specclauses))
8343 if (!stateClauseList_isDefined (old->info->fcn->specclauses))
8348 message ("Function %q redeclared using special clauses (can only "
8349 "be used in first declaration)",
8350 uentry_getName (unew)),
8351 uentry_whereDeclared (unew)))
8353 uentry_showWhereLast (old);
8357 /*@i23 need checking @*/
8359 old->info->fcn->specclauses = unew->info->fcn->specclauses;
8363 /*@i43 should be able to append? @*/
8365 stateClauseList_checkEqual (old, unew);
8366 stateClauseList_free (unew->info->fcn->specclauses);
8367 unew->info->fcn->specclauses = stateClauseList_undefined;
8370 /*@=branchstate@*/ /*@i23 shouldn't need this@*/
8373 DPRINTF (("After state: %s",
8374 uentry_unparseFull (old)));
8376 if (fileloc_isUndefined (old->whereDeclared))
8378 old->whereDeclared = fileloc_copy (unew->whereDeclared);
8380 else if (fileloc_isUndefined (unew->whereDeclared))
8382 unew->whereDeclared = fileloc_copy (old->whereDeclared);
8391 uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m)
8395 llassert (uentry_isValid (ue));
8396 llassert (uentry_isEitherConstant (ue));
8398 uval = ue->info->uconst->val;
8400 if (multiVal_isDefined (uval))
8402 if (multiVal_isDefined (m))
8404 if (!multiVal_equiv (uval, m))
8408 message ("%s %q defined with inconsistent value: %q",
8409 ekind_capName (ue->ukind),
8410 uentry_getName (ue),
8411 multiVal_unparse (m)),
8414 uentry_showWhereLastExtra (ue, multiVal_unparse (uval));
8422 ue->info->uconst->val = m;
8423 multiVal_free (uval);
8428 bool checkTypeConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew,
8431 bool typeError = FALSE;
8433 if (uentry_isStructTag (old) || uentry_isUnionTag (old))
8435 if (ctype_isSU (old->utype) && ctype_isSU (unew->utype))
8439 DPRINTF (("Check struct conformance: %s / %s",
8440 uentry_unparseFull (old),
8441 uentry_unparseFull (unew)));
8442 checkStructConformance (old, unew);
8447 if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
8449 llbug (message ("struct tags: bad types: %t / %t",
8450 old->utype, unew->utype));
8454 else if (uentry_isEnumTag (old))
8456 if (ctype_isEnum (old->utype) && ctype_isEnum (unew->utype))
8458 if (mustConform) checkEnumConformance (old, unew);
8462 if (!(ctype_isBogus (old->utype) || ctype_isBogus (unew->utype)))
8464 llbug (message ("enum! bad type: %s / %s", ctype_unparse (old->utype),
8465 ctype_unparse (unew->utype)));
8469 else if (!ctype_match (old->utype, unew->utype))
8471 DPRINTF (("Type mismatch: %s / %s",
8472 ctype_unparse (old->utype),
8473 ctype_unparse (unew->utype)));
8475 if (cstring_equal (uentry_rawName (old), context_getBoolName ()))
8477 ctype realt = ctype_realType (unew->utype);
8479 if (ctype_isRealInt (realt) || ctype_isChar (realt))
8481 unew->utype = ctype_bool;
8487 typeError = optgenerror
8489 message ("%q defined as %s", uentry_getName (old),
8490 ctype_unparse (realt)),
8491 uentry_whereDeclared (unew));
8499 ctype oldr = ctype_realType (old->utype);
8500 ctype newr = ctype_realType (unew->utype);
8502 if (ctype_isStruct (oldr) && ctype_isStruct (newr))
8504 checkStructConformance (old, unew);
8506 else if (ctype_isUnion (oldr) && ctype_isUnion (newr))
8508 checkStructConformance (old, unew);
8510 else if (ctype_isEnum (oldr) && ctype_isEnum (newr))
8512 checkEnumConformance (old, unew);
8514 else if (uentry_isConstant (old)
8515 && (ctype_isAbstract (oldr) && ctype_isEnum (newr)))
8517 /* okay...for now! (should check the type is reset later... */
8521 DPRINTF (("YABA!"));
8524 message ("%s %q %rdeclared with inconsistent type: %t",
8525 ekind_capName (unew->ukind),
8526 uentry_getName (unew),
8527 uentry_isDeclared (old),
8529 uentry_whereDeclared (unew)))
8531 uentry_showWhereLast (old);
8547 uentry_checkDatatypeConformance (/*@notnull@*/ uentry old,
8548 /*@notnull@*/ uentry unew,
8549 bool mustConform, bool completeConform)
8551 if (ctype_isDefined (unew->info->datatype->type))
8554 ** bool is hard coded here, since it is built into LCL.
8555 ** For now, we're stuck with LCL's types.
8558 if (ctype_isDirectBool (old->utype) &&
8559 cstring_equalLit (unew->uname, "bool"))
8561 /* if (!context_getFlag (FLG_ABSTRACTBOOL))
8562 evs 2000-07-25: removed
8564 unew->utype = ctype_bool;
8567 if (ctype_isUnknown (old->info->datatype->type))
8569 old->info->datatype->type = unew->info->datatype->type;
8573 DPRINTF (("Old: %s / New: %s",
8574 uentry_unparseFull (old),
8575 uentry_unparseFull (unew)));
8576 DPRINTF (("Types: %s / %s",
8577 ctype_unparse (old->info->datatype->type),
8578 ctype_unparse (unew->info->datatype->type)));
8580 if (ctype_matchDef (old->info->datatype->type,
8581 unew->info->datatype->type))
8590 ("Type %q %s with inconsistent type: %t",
8591 uentry_getName (unew),
8592 uentry_reDefDecl (old, unew),
8593 unew->info->datatype->type),
8594 uentry_whereDeclared (unew)))
8596 uentry_showWhereLastExtra
8597 (old, cstring_copy (ctype_unparse (old->info->datatype->type)));
8600 old->info->datatype->type = unew->info->datatype->type;
8605 if (unew->info->datatype->abs != MAYBE)
8607 if (ynm_isOff (old->info->datatype->abs)
8608 && ynm_isOn (unew->info->datatype->abs))
8610 if (!ctype_isDirectBool (old->utype))
8615 ("Datatype %q inconsistently %rdeclared as abstract type",
8616 uentry_getName (unew),
8617 uentry_isDeclared (old)),
8618 uentry_whereDeclared (unew)))
8620 uentry_showWhereLastPlain (old);
8624 else if (ynm_isOn (old->info->datatype->abs)
8625 && ynm_isOff (unew->info->datatype->abs))
8627 if (!ctype_isDirectBool (old->utype))
8632 ("Datatype %q inconsistently %rdeclared as concrete type",
8633 uentry_getName (unew),
8634 uentry_isDeclared (old)),
8635 uentry_whereDeclared (unew)))
8637 uentry_showWhereLastPlain (old);
8648 if (ynm_isOn (old->info->datatype->abs))
8650 old->sref = unew->sref;
8651 unew->info->datatype->mut = old->info->datatype->mut;
8654 && uentry_isReallySpecified (old))
8659 ("Datatype %q specified as abstract, "
8660 "but abstract annotation not used in declaration",
8661 uentry_getName (unew)),
8662 uentry_whereDeclared (unew)))
8664 uentry_showWhereLastPlain (old);
8670 unew->info->datatype->abs = old->info->datatype->abs;
8672 if (ynm_isMaybe (unew->info->datatype->mut))
8674 if (completeConform && ynm_isOff (old->info->datatype->mut)
8675 && uentry_isReallySpecified (old))
8680 ("Datatype %q specified as immutable, "
8681 "but immutable annotation not used in declaration",
8682 uentry_getName (unew)),
8683 uentry_whereDeclared (unew)))
8685 uentry_showWhereLastPlain (old);
8689 unew->info->datatype->mut = old->info->datatype->mut;
8691 else if (ynm_isMaybe (old->info->datatype->mut))
8693 old->info->datatype->mut = unew->info->datatype->mut;
8697 if (ynm_isOn (old->info->datatype->abs))
8699 if (ynm_isOn (old->info->datatype->mut) && ynm_isOff (unew->info->datatype->mut))
8703 message ("Datatype %q inconsistently %rdeclared as immutable",
8704 uentry_getName (unew),
8705 uentry_isDeclared (old)),
8706 uentry_whereDeclared (unew)))
8708 uentry_showWhereLastPlain (old);
8713 if (ynm_isOff (old->info->datatype->mut)
8714 && ynm_isOn (unew->info->datatype->mut))
8718 message ("Datatype %q inconsistently %rdeclared as mutable",
8719 uentry_getName (unew),
8720 uentry_isDeclared (old)),
8721 uentry_whereDeclared (unew)))
8723 uentry_showWhereLastPlain (old);
8728 old->info->datatype->mut = unew->info->datatype->mut;
8731 uentry_checkStateConformance (old, unew, mustConform, completeConform);
8735 uentry_checkConstantConformance (/*@notnull@*/ uentry old,
8736 /*@notnull@*/ uentry unew,
8738 /*@unused@*/ bool completeConform)
8740 multiVal oldVal = old->info->uconst->val;
8741 multiVal newVal = unew->info->uconst->val;
8743 if (multiVal_isDefined (oldVal))
8745 if (multiVal_isDefined (newVal))
8747 if (!multiVal_equiv (oldVal, newVal))
8752 message ("%s %q %rdeclared with inconsistent value: %q",
8753 ekind_capName (unew->ukind),
8754 uentry_getName (unew),
8755 uentry_isDeclared (old),
8756 multiVal_unparse (newVal)),
8757 uentry_whereDeclared (unew)))
8759 uentry_showWhereLastExtra (old, multiVal_unparse (oldVal));
8763 unew->info->uconst->val = multiVal_copy (oldVal);
8764 multiVal_free (newVal);
8773 old->info->uconst->val = multiVal_copy (newVal);
8778 uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old,
8779 /*@notnull@*/ uentry unew, bool mustConform,
8780 bool completeConform)
8782 bool typeError = FALSE;
8783 bool fcnConformance = FALSE;
8785 if (!ekind_equal (unew->ukind, old->ukind))
8788 ** okay, only if one is a function and the other is
8789 ** a variable of type function.
8792 if (unew->ukind == KENUMCONST
8793 && old->ukind == KCONST)
8795 old->ukind = KENUMCONST;
8799 if (unew->ukind == KFCN
8800 && old->ukind == KCONST
8801 && ctype_isUnknown (old->utype))
8804 ** When a function is defined with an unparam macro
8807 uentry_copyInto (old, unew);
8811 if (uentry_isExpandedMacro (old)
8812 && uentry_isEitherConstant (unew))
8814 uentry_copyInto (old, unew);
8818 if (uentry_isEndIter (unew))
8820 if (ctype_isUnknown (old->utype))
8822 if (!uentry_isSpecified (old)
8823 && uentry_isCodeDefined (unew))
8825 if (!fileloc_withinLines (uentry_whereDefined (old),
8826 uentry_whereDeclared (unew), 2))
8827 { /* bogus! will give errors if there is too much whitespace */
8831 ("Iterator finalized name %q does not match name in "
8832 "previous iter declaration (should be end_%q). This iter "
8833 "is declared at %q",
8834 uentry_getName (unew),
8835 uentry_getName (old),
8836 fileloc_unparse (uentry_whereDefined (old))),
8837 uentry_whereDeclared (old));
8841 uentry_copyInto (old, unew);
8846 KindConformanceError (old, unew, mustConform);
8850 if (uentry_isFunction (unew))
8852 if (uentry_isVariable (old))
8854 if (!ctype_isUnknown (old->utype))
8856 if (ctype_isFunction (old->utype))
8858 uentry_makeVarFunction (old);
8859 checkFunctionConformance (old, unew, mustConform,
8861 fcnConformance = TRUE;
8865 KindConformanceError (old, unew, mustConform);
8870 if (uentry_isExpandedMacro (old))
8872 if (fileloc_isUndefined (unew->whereDefined))
8874 unew->whereDefined = fileloc_update (unew->whereDefined,
8878 uentry_copyInto (old, unew);
8879 old->used = unew->used = TRUE;
8884 /* undeclared identifier */
8885 old->utype = unew->utype;
8886 uentry_makeVarFunction (old);
8887 checkFunctionConformance (old, unew, FALSE, FALSE);
8888 fcnConformance = TRUE;
8894 KindConformanceError (old, unew, mustConform);
8897 else if (uentry_isFunction (old) && uentry_isVariable (unew))
8899 if (!ctype_isUnknown (unew->utype))
8901 if (ctype_isFunction (unew->utype))
8903 uentry_makeVarFunction (unew);
8904 checkFunctionConformance (old, unew, mustConform, completeConform);
8905 fcnConformance = TRUE;
8909 KindConformanceError (old, unew, mustConform);
8914 KindConformanceError (old, unew, mustConform);
8919 KindConformanceError (old, unew, mustConform);
8925 ** check parameter lists for functions
8926 ** (before type errors, to get better messages
8929 if (uentry_isFunction (old))
8931 checkFunctionConformance (old, unew, mustConform, completeConform);
8932 fcnConformance = TRUE;
8936 if (!ctype_isUndefined (old->utype))
8938 typeError = checkTypeConformance (old, unew, mustConform);
8945 if (uentry_isEitherConstant (old) && uentry_isEitherConstant (unew))
8947 uentry_checkConstantConformance (old, unew, mustConform, completeConform);
8950 if (uentry_isDatatype (old) && uentry_isDatatype (unew))
8952 DPRINTF (("Check datatype: %s / %s",
8953 uentry_unparseFull (old),
8954 uentry_unparseFull (unew)));
8956 uentry_checkDatatypeConformance (old, unew, mustConform, completeConform);
8959 if (uentry_isVariable (old) && uentry_isVariable (unew))
8962 !ctype_matchDef (old->utype, unew->utype))
8967 ("Variable %q %s with inconsistent type (arrays and pointers are "
8968 "not identical in variable declarations): %t",
8969 uentry_getName (unew),
8970 uentry_reDefDecl (old, unew),
8972 uentry_whereDeclared (unew)))
8974 uentry_showWhereLast (old);
8977 ** Avoid repeated errors.
8980 if (uentry_isCodeDefined (old) && uentry_isCodeDefined (unew))
8982 old->whereDefined = fileloc_update (old->whereDefined,
8990 checkVarConformance (old, unew, mustConform, completeConform);
8995 /* old->utype = unew->utype; */
8999 if (ctype_isConj (old->utype))
9001 if (ctype_isConj (unew->utype))
9003 if (!ctype_sameAltTypes (old->utype, unew->utype))
9007 message ("%s %q inconsistently %rdeclared with "
9008 "alternate types %s "
9009 "(types match, but alternates are not identical, "
9010 "so checking may not be correct)",
9011 ekind_capName (uentry_getKind (old)),
9012 uentry_getName (unew),
9013 uentry_isDeclared (old),
9014 ctype_unparse (unew->utype)),
9015 uentry_whereDeclared (unew)))
9017 uentry_showWhereLastVal (old, ctype_unparse (old->utype));
9021 old->utype = unew->utype;
9028 if (ctype_isUnknown (old->utype))
9030 old->utype = unew->utype;
9035 if (unew->ukind == old->ukind)
9038 unew->info = uinfo_copy (old->info, old->ukind);
9041 sRef_storeState (old->sref);
9042 sRef_storeState (unew->sref);
9045 static void uentry_mergeConstraints (uentry spec, uentry def)
9047 if (uentry_isFunction (def))
9049 DPRINTF (("Here: %s / %s",
9050 uentry_unparseFull (spec),
9051 uentry_unparseFull (def)));
9053 if (functionConstraint_isDefined (def->info->fcn->preconditions))
9055 if (fileloc_isXHFile (uentry_whereLast (def)))
9057 llassert (uentry_isFunction (spec));
9058 spec->info->fcn->preconditions = functionConstraint_conjoin (spec->info->fcn->preconditions,
9059 def->info->fcn->preconditions);
9066 ("Preconditions for %q redeclared. Dropping previous precondition: %q",
9067 uentry_getName (spec),
9068 functionConstraint_unparse (spec->info->fcn->preconditions)),
9069 uentry_whereLast (def)))
9071 uentry_showWhereSpecified (spec);
9074 functionConstraint_free (spec->info->fcn->preconditions);
9075 spec->info->fcn->preconditions = def->info->fcn->preconditions;
9078 def->info->fcn->preconditions = functionConstraint_undefined;
9081 if (functionConstraint_isDefined (def->info->fcn->postconditions))
9083 if (fileloc_isXHFile (uentry_whereLast (def)))
9085 llassert (uentry_isFunction (spec));
9086 DPRINTF (("Post: %s /++/ %s",
9087 functionConstraint_unparse (spec->info->fcn->postconditions),
9088 functionConstraint_unparse (def->info->fcn->postconditions)));
9089 spec->info->fcn->postconditions = functionConstraint_conjoin (spec->info->fcn->postconditions,
9090 def->info->fcn->postconditions);
9091 def->info->fcn->postconditions = functionConstraint_undefined;
9092 DPRINTF (("Conjoined post: %s", functionConstraint_unparse (spec->info->fcn->postconditions)));
9099 ("Postconditions for %q redeclared. Dropping previous postcondition: %q",
9100 uentry_getName (spec),
9101 functionConstraint_unparse (spec->info->fcn->postconditions)),
9102 uentry_whereLast (def)))
9104 uentry_showWhereSpecified (spec);
9107 functionConstraint_free (spec->info->fcn->postconditions);
9108 spec->info->fcn->postconditions = def->info->fcn->postconditions;
9109 def->info->fcn->postconditions = functionConstraint_undefined;
9116 ** modifies spec to reflect def, reports any inconsistencies
9120 uentry_mergeEntries (uentry spec, /*@only@*/ uentry def)
9122 llassert (uentry_isValid (spec));
9123 llassert (uentry_isValid (def));
9124 llassert (cstring_equal (spec->uname, def->uname));
9126 DPRINTF (("Merge entries: %s / %s",
9127 uentry_unparseFull (spec),
9128 uentry_unparseFull (def)));
9130 uentry_mergeConstraints (spec, def);
9132 uentry_checkConformance (spec, def, TRUE,
9133 context_getFlag (FLG_NEEDSPEC));
9135 DPRINTF (("Merge entries after conform: %s / %s",
9136 uentry_unparseFull (spec),
9137 uentry_unparseFull (def)));
9139 /* was: !(fileloc_isImport (uentry_whereSpecified (spec)))); */
9142 ** okay, declarations conform. Propagate extra information.
9145 uentry_setDefined (spec, uentry_whereDefined (def));
9146 uentry_setDeclared (spec, uentry_whereDeclared (def));
9148 if (uentry_isStatic (def))
9152 message ("%s %q specified, but declared as static",
9153 ekind_capName (def->ukind),
9154 uentry_getName (def)),
9155 uentry_whereDeclared (def)))
9157 uentry_showWhereSpecified (spec);
9162 spec->storageclass = def->storageclass;
9165 sRef_storeState (spec->sref);
9167 spec->used = def->used || spec->used;
9168 spec->hasNameError |= def->hasNameError;
9172 if (!spec->hasNameError)
9174 uentry_checkName (spec);
9183 ** Can't generate function redeclaration errors when the
9184 ** entries are merged, since we don't yet know if its the
9185 ** definition of the function.
9189 uentry_clearDecl (void)
9191 posRedeclared = uentry_undefined;
9192 fileloc_free (posLoc);
9193 posLoc = fileloc_undefined;
9197 uentry_checkDecl (void)
9199 if (uentry_isValid (posRedeclared) && !fileloc_isXHFile (posLoc))
9201 llassert (fileloc_isDefined (posLoc));
9203 if (uentry_isCodeDefined (posRedeclared))
9205 if (optgenerror (FLG_REDECL,
9206 message ("%s %q declared after definition",
9207 ekind_capName (posRedeclared->ukind),
9208 uentry_getName (posRedeclared)),
9211 llgenindentmsg (message ("Definition of %q",
9212 uentry_getName (posRedeclared)),
9213 posRedeclared->whereDeclared);
9218 if (optgenerror (FLG_REDECL,
9219 message ("%s %q declared more than once",
9220 ekind_capName (posRedeclared->ukind),
9221 uentry_getName (posRedeclared)),
9224 llgenindentmsg (message ("Previous declaration of %q",
9225 uentry_getName (posRedeclared)),
9226 posRedeclared->whereDeclared);
9231 fileloc_free (posLoc);
9232 posLoc = fileloc_undefined;
9233 posRedeclared = uentry_undefined;
9237 ** Redefinition of old as unew.
9238 ** modifies old to reflect unew, reports any inconsistencies
9242 uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew)
9244 fileloc olddef = uentry_whereDeclared (old);
9245 fileloc unewdef = uentry_whereDeclared (unew);
9249 DPRINTF (("uentry merge: %s / %s",
9250 uentry_unparseFull (old),
9251 uentry_unparseFull (unew)));
9253 if (uentry_isExtern (unew))
9255 uentry_setUsed (old, unewdef);
9259 fileloc_isUndefined (olddef)
9260 && fileloc_isDefined (uentry_whereDefined (old))
9261 && !uentry_isExpandedMacro (old);
9263 if (!context_getFlag (FLG_INCONDEFSLIB)
9264 && (fileloc_isLib (olddef) || fileloc_isImport (olddef)))
9266 mustConform = FALSE;
9273 llassert (uentry_isValid (old));
9274 llassert (uentry_isValid (unew));
9275 llassert (cstring_equal (old->uname, unew->uname));
9278 ** should check old one was extern!
9281 if (uentry_isStatic (old))
9283 if (!(uentry_isStatic (unew)))
9287 message ("%s %q shadows static declaration",
9288 ekind_capName (unew->ukind),
9289 uentry_getName (unew)),
9292 uentry_showWhereLast (old);
9297 uentry_setDeclDef (old, unewdef);
9300 else if (uentry_isStatic (unew))
9302 uentry_setDeclDef (old, unewdef);
9304 else if (uentry_isExtern (old))
9306 uentry_setDeclared (old, unewdef);
9310 if (!uentry_isExtern (unew) && !uentry_isForward (old)
9311 && !fileloc_equal (olddef, unewdef)
9312 && !fileloc_isUndefined (olddef)
9313 && !fileloc_isUndefined (unewdef)
9314 && !fileloc_isBuiltin (olddef)
9315 && !fileloc_isBuiltin (unewdef)
9316 && !uentry_isYield (old)
9317 && !(fileloc_isLib (olddef) || fileloc_isImport (olddef)))
9319 if (uentry_isVariable (old) || uentry_isVariable (unew))
9321 ; /* will report redeclaration error later */
9325 if (fileloc_isDefined (uentry_whereDefined (old)))
9329 message ("%s %q defined more than once",
9330 ekind_capName (unew->ukind),
9331 uentry_getName (unew)),
9332 uentry_whereLast (unew)))
9335 (message ("Previous definition of %q",
9336 uentry_getName (old)),
9337 uentry_whereLast (old));
9340 if (uentry_isDatatype (old) || uentry_isAnyTag (old))
9342 uentry_copyInto (old, unew);
9343 old->sref = sRef_saveCopy (old->sref);
9351 if (fileloc_isLib (olddef)
9352 || fileloc_isUndefined (olddef)
9353 || fileloc_isImport (olddef))
9355 if (uentry_isExtern (unew))
9357 if (uentry_isExtern (old)
9358 || (fileloc_isDefined (uentry_whereDeclared (old))
9359 && (!fileloc_equal (uentry_whereDeclared (old),
9360 uentry_whereDefined (old)))))
9364 message ("%s %q declared more than once",
9365 ekind_capName (unew->ukind),
9366 uentry_getName (unew)),
9367 unew->whereDeclared))
9370 (message ("Previous declaration of %q",
9371 uentry_getName (old)),
9372 old->whereDeclared);
9376 uentry_setExtern (old);
9380 uentry_setDefined (old, unewdef);
9386 uentry_mergeConstraints (old, unew);
9388 uentry_checkConformance (old, unew, mustConform, FALSE);
9390 old->used = old->used || unew->used;
9391 old->uses = filelocList_append (old->uses, unew->uses);
9392 unew->uses = filelocList_undefined;
9394 sRef_storeState (old->sref);
9395 sRef_storeState (unew->sref);
9399 old->whereDefined = fileloc_update (old->whereDefined,
9404 ** No redeclaration errors for functions here, since we
9405 ** don't know if this is the definition of the function.
9408 if (fileloc_isUser (old->whereDeclared)
9409 && fileloc_isUser (unew->whereDeclared)
9410 && !fileloc_equal (old->whereDeclared, unew->whereDeclared)
9411 && !fileloc_isDefined (unew->whereDefined))
9413 if (uentry_isFunction (old))
9415 /*@-temptrans@*/ posRedeclared = old; /*@=temptrans@*/
9416 posLoc = fileloc_update (posLoc, unew->whereDeclared);
9420 if (optgenerror (FLG_REDECL,
9421 message ("%s %q declared more than once",
9422 ekind_capName (unew->ukind),
9423 uentry_getName (unew)),
9424 unew->whereDeclared))
9426 llgenindentmsg (message ("Previous declaration of %q",
9427 uentry_getName (old)),
9428 old->whereDeclared);
9433 if (fileloc_isUndefined (old->whereDefined))
9435 old->whereDefined = fileloc_update (old->whereDefined, unew->whereDefined);
9439 if (!context_processingMacros ()
9440 && fileloc_isUser (old->whereDefined)
9441 && fileloc_isUser (unew->whereDefined)
9442 && !fileloc_equal (old->whereDefined, unew->whereDefined))
9444 if (uentry_isVariable (unew) || uentry_isFunction (unew))
9446 if (uentry_isVariable (unew)
9447 && uentry_isExtern (unew))
9449 if (optgenerror (FLG_REDECL,
9450 message ("%s %q declared after definition",
9451 ekind_capName (unew->ukind),
9452 uentry_getName (unew)),
9453 unew->whereDeclared))
9455 llgenindentmsg (message ("Definition of %q",
9456 uentry_getName (old)),
9462 if (optgenerror (FLG_REDEF,
9463 message ("%s %q redefined",
9464 ekind_capName (unew->ukind),
9465 uentry_getName (unew)),
9466 unew->whereDefined))
9468 llgenindentmsg (message ("Previous definition of %q",
9469 uentry_getName (old)),
9477 if (uentry_isExternal (unew))
9479 old->whereDefined = fileloc_createExternal ();
9482 if (unew->hasNameError)
9484 old->hasNameError = TRUE;
9489 if (!old->hasNameError)
9491 uentry_checkName (old);
9494 llassert (!ctype_isUndefined (old->utype));
9498 uentry_copyState (uentry res, uentry other)
9500 llassert (uentry_isValid (res));
9501 llassert (uentry_isValid (other));
9503 res->used = other->used;
9505 res->info->var->kind = other->info->var->kind;
9506 res->info->var->defstate = other->info->var->defstate;
9507 res->info->var->nullstate = other->info->var->nullstate;
9508 res->info->var->checked = other->info->var->checked;
9510 sRef_copyState (res->sref, other->sref);
9514 uentry_sameKind (uentry u1, uentry u2)
9516 if (uentry_isValid (u1) && uentry_isValid (u2))
9518 if (uentry_isVar (u1) && uentry_isVar (u2))
9520 ctype c1 = u1->utype;
9521 ctype c2 = u2->utype;
9523 if (ctype_isUnknown (c1) || ctype_isUnknown (c2)) return FALSE;
9526 ** both functions, or both not functions
9529 return (bool_equal (ctype_isFunction (c1), ctype_isFunction (c2)));
9533 return ((u1->ukind == u2->ukind));
9540 static void uentry_copyInto (/*@unique@*/ uentry unew, uentry old)
9542 llassert (uentry_isValid (unew));
9543 llassert (uentry_isValid (old));
9545 unew->ukind = old->ukind;
9546 unew->uname = cstring_copy (old->uname);
9547 unew->utype = old->utype;
9549 unew->whereSpecified = fileloc_copy (old->whereSpecified);
9550 unew->whereDefined = fileloc_copy (old->whereDefined);
9551 unew->whereDeclared = fileloc_copy (old->whereDeclared);
9553 unew->sref = sRef_saveCopy (old->sref); /* Memory leak! */
9554 unew->used = old->used;
9556 unew->isPrivate = old->isPrivate;
9557 unew->hasNameError = old->hasNameError;
9558 unew->uses = filelocList_undefined;
9560 unew->storageclass = old->storageclass;
9561 unew->info = uinfo_copy (old->info, old->ukind);
9566 uentry_copy (uentry e)
9568 if (uentry_isValid (e))
9570 uentry enew = uentry_alloc ();
9571 DPRINTF (("copy: %s", uentry_unparseFull (e)));
9572 uentry_copyInto (enew, e);
9573 DPRINTF (("Here we are..."));
9574 DPRINTF (("original: %s", uentry_unparseFull (e)));
9575 DPRINTF (("copy: %s", uentry_unparse (enew)));
9576 DPRINTF (("copy: %s", uentry_unparseFull (enew)));
9581 return uentry_undefined;
9586 uentry_setState (uentry res, uentry other)
9588 llassert (uentry_isValid (res));
9589 llassert (uentry_isValid (other));
9591 llassert (res->ukind == other->ukind);
9592 llassert (res->ukind == KVAR);
9594 res->sref = sRef_saveCopy (other->sref);
9595 res->used = other->used;
9596 filelocList_free (res->uses);
9597 res->uses = other->uses;
9598 other->uses = filelocList_undefined;
9599 res->lset = other->lset;
9603 uentry_mergeUses (uentry res, uentry other)
9605 llassert (uentry_isValid (res));
9606 llassert (uentry_isValid (other));
9608 res->used = other->used || res->used;
9609 res->lset = other->lset || res->lset;
9610 res->uses = filelocList_append (res->uses, other->uses);
9611 other->uses = filelocList_undefined;
9616 ** This is a really ugly routine.
9618 ** gack...fix this one day.
9623 ** >> res is the false branch, other is the true branch (or continuation)
9625 ** >> res is the true branch, other is the false branch (or continutation)
9632 ** References not effected by res are propagated from other.
9636 branchStateError (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other,
9637 bool flip, clause cl, fileloc loc)
9641 message ("%s %q is %s %s, but %s %s.",
9642 ekind_capName (res->ukind), uentry_getName (res),
9643 sRef_stateVerb (res->sref), clause_nameFlip (cl, flip),
9644 sRef_stateAltVerb (res->sref), clause_nameFlip (cl, !flip)),
9647 if (sRef_isDead (res->sref))
9649 sRef_showStateInfo (res->sref);
9651 else if (sRef_isKept (res->sref))
9653 sRef_showAliasInfo (res->sref);
9655 else /* dependent */
9657 sRef_showAliasInfo (res->sref);
9658 sRef_showAliasInfo (other->sref);
9661 sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
9665 static bool incompatibleStates (sRef rs, sRef os)
9667 alkind rk = sRef_getAliasKind (rs);
9668 alkind ok = sRef_getAliasKind (os);
9670 if (alkind_isError (rk) || alkind_isError (ok))
9676 return ((sRef_isDead (rs)
9677 || (alkind_isKept (rk) && !alkind_isKept (ok))
9678 || (alkind_isDependent (rk)
9679 && !alkind_isDependent (ok) && !alkind_isTemp (ok)))
9680 && (sRef_isAllocated (os) || sRef_isStateDefined (os)));
9685 branchStateAltError (/*@notnull@*/ uentry res,
9686 /*@notnull@*/ uentry other, bool flip,
9687 clause cl, fileloc loc)
9691 message ("%s %q is %s %s, but %s %s.",
9692 ekind_capName (res->ukind), uentry_getName (res),
9693 sRef_stateVerb (other->sref), clause_nameFlip (cl, flip),
9694 sRef_stateAltVerb (other->sref), clause_nameFlip (cl, !flip)),
9697 if (sRef_isDead (other->sref))
9699 sRef_showStateInfo (other->sref);
9703 sRef_showAliasInfo (other->sref);
9706 sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined);
9707 sRef_setDefinedComplete (res->sref, fileloc_undefined);
9709 sRef_setAliasKind (other->sref, AK_ERROR, fileloc_undefined);
9710 sRef_setDefinedComplete (other->sref, fileloc_undefined);
9715 ** A reference is relevant for certain checks, only if it
9716 ** is not definitely null on this path (but not declared
9717 ** to always be null.)
9720 static bool uentry_relevantReference (sRef sr, bool flip)
9722 if (sRef_isKept (sr) || sRef_isDependent (sr))
9730 return !sRef_definitelyNullContext (sr);
9734 return !sRef_definitelyNullAltContext (sr);
9740 uentry_mergeAliasStates (uentry res, uentry other, fileloc loc,
9741 bool mustReturn, bool flip, bool opt,
9744 DPRINTF (("Merge alias states: %s / %s",
9745 uentry_unparseFull (res),
9746 uentry_unparseFull (other)));
9748 if (sRef_isValid (res->sref))
9753 if (incompatibleStates (res->sref, other->sref))
9757 if (sRef_isThroughArrayFetch (res->sref)
9758 && !context_getFlag (FLG_STRICTBRANCHSTATE))
9760 if (sRef_isKept (res->sref) || sRef_isKept (other->sref))
9762 sRef_maybeKill (res->sref, loc);
9764 else if (sRef_isPossiblyDead (other->sref))
9766 sRef_maybeKill (res->sref, loc);
9775 if (uentry_relevantReference (other->sref, flip))
9778 if (sRef_isLocalParamVar (res->sref)
9779 && (sRef_isLocalState (other->sref)
9780 || sRef_isDependent (other->sref)))
9782 if (sRef_isDependent (res->sref))
9784 sRef_setDependent (other->sref, loc);
9788 sRef_setDefState (res->sref, SS_UNUSEABLE, loc);
9793 branchStateError (res, other, flip, cl, loc);
9798 if (sRef_isKept (res->sref))
9800 sRef_setKept (other->sref, loc);
9805 if (incompatibleStates (other->sref, res->sref))
9807 if (uentry_relevantReference (res->sref, !flip))
9809 if (sRef_isLocalParamVar (res->sref)
9810 && (sRef_isDependent (res->sref)
9811 || sRef_isLocalState (res->sref)))
9813 if (sRef_isDependent (other->sref))
9815 sRef_setDependent (res->sref, loc);
9819 sRef_setDefState (res->sref, SS_UNUSEABLE, loc);
9824 if (sRef_isParam (other->sref))
9827 ** If the local variable associated
9828 ** with the param has the correct state,
9830 ** (e.g., free (s); s = new(); ...
9833 uentry uvar = usymtab_lookupSafe (other->uname);
9835 if (uentry_isValid (uvar)
9836 && ((sRef_isDead (other->sref)
9837 && sRef_isOnly (uvar->sref))
9838 || (sRef_isDependent (other->sref)
9839 && sRef_isOwned (uvar->sref))))
9845 branchStateAltError (res, other,
9851 DPRINTF (("Here: %s / %s",
9852 uentry_unparseFull (res),
9853 uentry_unparseFull (other)));
9855 branchStateAltError (res, other,
9862 if (sRef_isKept (other->sref))
9864 sRef_setKept (res->sref, loc);
9870 DPRINTF (("Merge opt..."));
9871 sRef_mergeOptState (res->sref, other->sref, cl, loc);
9872 DPRINTF (("Done!"));
9876 sRef_mergeState (res->sref, other->sref, cl, loc);
9881 if (sRef_isModified (other->sref))
9883 sRef_setModified (res->sref);
9890 uentry_mergeValueStates (uentry res, uentry other, fileloc loc)
9895 DPRINTF (("Merge values: %s / %s", sRef_unparseFull (res->sref), sRef_unparseFull (other->sref)));
9897 rvalues = sRef_getValueTable (res->sref);
9898 ovalues = sRef_getValueTable (other->sref);
9900 if (valueTable_isUndefined (ovalues))
9902 DPRINTF (("No value table: %s", sRef_unparseFull (other->sref)));
9905 else if (valueTable_isUndefined (rvalues))
9908 ** Copy values from other
9912 DPRINTF (("Has value table: %s", sRef_unparseFull (other->sref)));
9913 DPRINTF (("No value table: %s", sRef_unparseFull (res->sref)));
9918 valueTable_elements (ovalues, fkey, fval) {
9920 metaStateInfo minfo;
9921 stateCombinationTable sctable;
9925 tval = valueTable_lookup (rvalues, fkey);
9927 DPRINTF (("Merge value: %s / %s X %s", fkey,
9928 stateValue_unparse (fval), stateValue_unparse (tval)));
9930 minfo = context_lookupMetaStateInfo (fkey);
9931 llassert (stateValue_isDefined (tval));
9933 if (metaStateInfo_isUndefined (minfo) || !stateValue_isDefined (tval))
9935 DPRINTF (("Cannot find meta state for: %s", fkey));
9940 llassert (metaStateInfo_isDefined (minfo));
9942 if (stateValue_isError (fval)
9943 || sRef_definitelyNullContext (res->sref))
9945 sRef_setMetaStateValueComplete (res->sref,
9946 fkey, stateValue_getValue (fval),
9948 DPRINTF (("Setting res: %s", sRef_unparseFull (res->sref)));
9950 else if (stateValue_isError (tval)
9951 || sRef_definitelyNullAltContext (other->sref))
9953 DPRINTF (("Other branch is definitely null!"));
9957 DPRINTF (("Check: %s / %s / %s / %s", fkey,
9958 metaStateInfo_unparse (minfo),
9959 stateValue_unparse (fval),
9960 stateValue_unparse (tval)));
9962 DPRINTF (("state values: %d / %d",
9963 stateValue_getValue (fval), stateValue_getValue (tval)));
9965 sctable = metaStateInfo_getMergeTable (minfo);
9967 DPRINTF (("Merge table: %s",
9968 stateCombinationTable_unparse (sctable)));
9970 msg = cstring_undefined;
9972 nval = stateCombinationTable_lookup (sctable,
9973 stateValue_getValue (fval),
9974 stateValue_getValue (tval),
9977 DPRINTF (("nval: %d / %d / %d", nval,
9978 stateValue_getValue (fval), stateValue_getValue (tval)));
9980 if (cstring_isDefined (msg))
9982 /*@i32 print extra info for assignments@*/
9984 if (uentry_isGlobalMarker (res))
9989 ("Control branches merge with incompatible global states (%s and %s): %s",
9990 metaStateInfo_unparseValue (minfo, stateValue_getValue (fval)),
9991 metaStateInfo_unparseValue (minfo, stateValue_getValue (tval)),
9995 sRef_showMetaStateInfo (res->sref, fkey);
9996 sRef_showMetaStateInfo (other->sref, fkey);
10004 ("Control branches merge with incompatible states for %q (%s and %s): %s",
10005 uentry_getName (res),
10006 metaStateInfo_unparseValue (minfo, stateValue_getValue (fval)),
10007 metaStateInfo_unparseValue (minfo, stateValue_getValue (tval)),
10011 sRef_showMetaStateInfo (res->sref, fkey);
10012 sRef_showMetaStateInfo (other->sref, fkey);
10013 DPRINTF (("Res: %s", sRef_unparseFull (res->sref)));
10014 DPRINTF (("Other: %s", sRef_unparseFull (other->sref)));
10015 DPRINTF (("Null: %s / %s",
10016 bool_unparse (usymtab_isDefinitelyNull (res->sref)),
10017 bool_unparse (usymtab_isDefinitelyNull (other->sref))));
10023 if (nval == stateValue_getValue (fval)
10024 && nval != stateValue_getValue (tval))
10026 loc = stateValue_getLoc (fval);
10028 else if (nval == stateValue_getValue (tval)
10029 && nval != stateValue_getValue (fval))
10031 loc = stateValue_getLoc (tval);
10038 if (stateValue_getValue (sRef_getMetaStateValue (res->sref, fkey)) == nval
10039 && nval == stateValue_getValue (fval)
10040 && nval == stateValue_getValue (tval))
10046 sRef_setMetaStateValueComplete (res->sref, fkey, nval, loc);
10050 } end_valueTable_elements ;
10056 uentry_mergeSetStates (uentry res, uentry other, /*@unused@*/ fileloc loc,
10057 bool flip, clause cl)
10059 if (cl == DOWHILECLAUSE)
10061 res->used = other->used || res->used;
10062 res->lset = other->lset || res->lset;
10063 res->uses = filelocList_append (res->uses, other->uses);
10064 other->uses = filelocList_undefined;
10068 if (sRef_isMacroParamRef (res->sref)
10069 && !uentry_isSefParam (other)
10070 && !uentry_isSefParam (res))
10072 bool hasError = FALSE;
10074 if (bool_equal (res->used, other->used))
10076 res->used = other->used;
10080 if (other->used && !flip)
10085 message ("Macro parameter %q used in true clause, "
10086 "but not in false clause",
10087 uentry_getName (res)),
10088 uentry_whereDeclared (res));
10095 message ("Macro parameter %q used in false clause, "
10096 "but not in true clause",
10097 uentry_getName (res)),
10098 uentry_whereDeclared (res));
10104 /* make it sef now, prevent more errors */
10105 res->info->var->kind = VKREFSEFPARAM;
10111 res->used = other->used || res->used;
10112 res->lset = other->lset || res->lset;
10113 res->uses = filelocList_append (res->uses, other->uses);
10114 other->uses = filelocList_undefined;
10120 uentry_mergeState (uentry res, uentry other, fileloc loc,
10121 bool mustReturn, bool flip, bool opt,
10124 llassert (uentry_isValid (res));
10125 llassert (uentry_isValid (other));
10127 llassert (res->ukind == other->ukind);
10128 llassert (res->ukind == KVAR);
10130 DPRINTF (("Merge state: %s / %s", uentry_unparseFull (res),
10131 uentry_unparseFull (other)));
10133 uentry_mergeAliasStates (res, other, loc, mustReturn, flip, opt, cl);
10134 uentry_mergeValueStates (res, other, loc);
10135 uentry_mergeSetStates (res, other, loc, flip, cl);
10138 void uentry_setUsed (uentry e, fileloc loc)
10140 static bool firstTime = TRUE;
10141 static bool showUses = FALSE;
10142 static bool exportLocal = FALSE;
10144 DPRINTF (("Used: %s / %s", uentry_unparse (e), fileloc_unparse (loc)));
10148 /* need to track uses is FLG_SHOWUSES or FLG_EXPORTLOCAL is true */
10150 showUses = context_getFlag (FLG_SHOWUSES);
10151 exportLocal = context_maybeSet (FLG_EXPORTLOCAL);
10156 if (uentry_isValid (e))
10160 if (warnClause_isDefined (e->warn))
10162 flagSpec flg = warnClause_getFlag (e->warn);
10165 if (warnClause_hasMessage (e->warn))
10167 msg = cstring_copy (warnClause_getMessage (e->warn));
10171 msg = message ("Use of possibly dangerous %s",
10172 uentry_ekindNameLC (e));
10176 message ("%q: %q", msg, uentry_getName (e)),
10180 if (sRef_isMacroParamRef (e->sref))
10182 if (uentry_isYield (e) || uentry_isSefParam (e))
10188 if (context_inConditional ())
10192 message ("Macro parameter %q used in conditionally "
10193 "executed code (may or may not be "
10194 "evaluated exactly once)",
10195 uentry_getName (e)),
10198 e->info->var->kind = VKREFSEFPARAM;
10207 message ("Macro parameter %q used more than once",
10208 uentry_getName (e)),
10209 uentry_whereDeclared (e)))
10211 e->info->var->kind = VKREFSEFPARAM;
10218 if ((dp = uentry_directParamNo (e)) >= 0)
10220 uentry_setUsed (usymtab_getParam (dp), loc);
10225 if (!sRef_isLocalVar (e->sref))
10229 e->uses = filelocList_add (e->uses, fileloc_copy (loc));
10235 if (context_inMacro ())
10237 e->uses = filelocList_addUndefined (e->uses);
10241 e->uses = filelocList_addDifferentFile
10243 uentry_whereDeclared (e),
10252 bool uentry_isReturned (uentry u)
10254 return (uentry_isValid (u) && uentry_isVar (u)
10255 && (u->info->var->kind == VKRETPARAM
10256 || u->info->var->kind == VKSEFRETPARAM));
10259 /*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args)
10261 llassert (uentry_isRealFunction (u));
10263 if (ctype_isFunction (u->utype) && sRef_isStateSpecial (uentry_getSref (u)))
10265 stateClauseList clauses = uentry_getStateClauseList (u);
10266 sRef res = sRef_makeNew (ctype_getReturnType (u->utype), u->sref, u->uname);
10268 DPRINTF (("Returned: %s", sRef_unparseFull (res)));
10269 sRef_setAllocated (res, g_currentloc);
10271 DPRINTF (("ensures clause: %s / %s", uentry_unparse (u),
10272 stateClauseList_unparse (clauses)));
10274 stateClauseList_postElements (clauses, cl)
10276 if (!stateClause_isGlobal (cl))
10278 sRefSet refs = stateClause_getRefs (cl);
10279 sRefMod modf = stateClause_getEffectFunction (cl);
10281 sRefSet_elements (refs, el)
10283 sRef base = sRef_getRootBase (el);
10285 if (sRef_isResult (base))
10289 sRef sr = sRef_fixBase (el, res);
10290 modf (sr, g_currentloc);
10297 } end_sRefSet_elements ;
10299 } end_stateClauseList_postElements ;
10307 sRefSet prefs = sRefSet_new ();
10308 sRef res = sRef_undefined;
10311 params = uentry_getParams (u);
10313 uentryList_elements (params, current)
10315 if (uentry_isReturned (current))
10317 if (exprNodeList_size (args) >= paramno)
10319 exprNode ecur = exprNodeList_nth (args, paramno);
10320 sRef tref = exprNode_getSref (ecur);
10322 DPRINTF (("Returned reference: %s", sRef_unparseFull (tref)));
10324 if (sRef_isValid (tref))
10326 sRef tcref = sRef_copy (tref);
10328 usymtab_addForceMustAlias (tcref, tref); /* evans 2001-05-27 */
10330 if (sRef_isDead (tcref))
10332 sRef_setDefined (tcref, g_currentloc);
10333 sRef_setOnly (tcref, g_currentloc);
10336 if (sRef_isRefCounted (tcref))
10338 /* could be a new ref now (but only if its returned) */
10339 sRef_setAliasKindComplete (tcref, AK_ERROR, g_currentloc);
10342 sRef_makeSafe (tcref);
10343 prefs = sRefSet_insert (prefs, tcref);
10349 } end_uentryList_elements ;
10351 if (sRefSet_size (prefs) > 0)
10353 nstate n = sRef_getNullState (u->sref);
10355 if (sRefSet_size (prefs) == 1)
10357 res = sRefSet_choose (prefs);
10361 /* should this ever happen? */ /*@i534 evans 2001-05-27 */
10362 res = sRefSet_mergeIntoOne (prefs);
10365 if (nstate_isKnown (n))
10367 sRef_setNullState (res, n, g_currentloc);
10372 if (ctype_isFunction (u->utype))
10374 DPRINTF (("Making new from %s -->", uentry_unparseFull (u)));
10375 res = sRef_makeNew (ctype_getReturnType (u->utype), u->sref, u->uname);
10379 res = sRef_makeNew (ctype_unknown, u->sref, u->uname);
10382 if (sRef_isRefCounted (res))
10384 sRef_setAliasKind (res, AK_NEWREF, g_currentloc);
10389 if (sRef_getNullState (res) == NS_ABSNULL)
10391 ctype ct = ctype_realType (u->utype);
10393 if (ctype_isAbstract (ct))
10395 sRef_setNotNull (res, g_currentloc);
10399 if (ctype_isUser (ct))
10401 sRef_setStateFromUentry (res, usymtab_getTypeEntry (ctype_typeId (ct)));
10405 sRef_setNotNull (res, g_currentloc);
10410 if (sRef_isRefCounted (res))
10412 sRef_setAliasKind (res, AK_NEWREF, g_currentloc);
10414 else if (sRef_isKillRef (res))
10416 sRef_setAliasKind (res, AK_REFCOUNTED, g_currentloc);
10423 ak = sRef_getAliasKind (res);
10425 if (alkind_isImplicit (ak))
10427 sRef_setAliasKind (res,
10428 alkind_fixImplicit (ak),
10432 sRefSet_free (prefs);
10434 DPRINTF (("Returns ref: %s", sRef_unparseFull (res)));
10439 static bool uentry_isRefCounted (uentry ue)
10441 ctype ct = uentry_getType (ue);
10443 if (ctype_isFunction (ct))
10445 return (ctype_isRefCounted (ctype_getReturnType (ct)));
10449 return (ctype_isRefCounted (ct));
10454 ** old was declared yield in the specification.
10455 ** new is declared in the iter implementation.
10458 void uentry_checkYieldParam (uentry old, uentry unew)
10462 llassert (uentry_isVariable (old));
10463 llassert (uentry_isVariable (unew));
10465 unew->info->var->kind = VKYIELDPARAM;
10466 (void) checkTypeConformance (old, unew, TRUE);
10467 checkVarConformance (old, unew, TRUE, FALSE);
10469 /* get rid of param marker */
10471 name = uentry_getName (unew);
10472 cstring_free (unew->uname);
10473 unew->uname = name;
10474 unew->info->var->kind = VKREFYIELDPARAM;
10476 uentry_setUsed (old, fileloc_undefined);
10477 uentry_setUsed (unew, fileloc_undefined);
10480 /*@observer@*/ cstring
10481 uentry_ekindName (uentry ue)
10483 if (uentry_isValid (ue))
10488 return cstring_makeLiteralTemp ("<Error: invalid uentry>");
10490 return cstring_makeLiteralTemp ("Datatype");
10492 return cstring_makeLiteralTemp ("Enum member");
10494 return cstring_makeLiteralTemp ("Constant");
10496 if (uentry_isParam (ue))
10498 return cstring_makeLiteralTemp ("Parameter");
10500 else if (uentry_isExpandedMacro (ue))
10502 return cstring_makeLiteralTemp ("Expanded macro");
10506 return cstring_makeLiteralTemp ("Variable");
10509 return cstring_makeLiteralTemp ("Function");
10511 return cstring_makeLiteralTemp ("Iterator");
10513 return cstring_makeLiteralTemp ("Iterator finalizer");
10515 return cstring_makeLiteralTemp ("Struct tag");
10517 return cstring_makeLiteralTemp ("Union tag");
10519 return cstring_makeLiteralTemp ("Enum tag");
10521 return cstring_makeLiteralTemp ("Optional parameters");
10526 return cstring_makeLiteralTemp ("<Undefined>");
10532 /*@observer@*/ cstring
10533 uentry_ekindNameLC (uentry ue)
10535 if (uentry_isValid (ue))
10540 return cstring_makeLiteralTemp ("<error: invalid uentry>");
10542 return cstring_makeLiteralTemp ("datatype");
10544 return cstring_makeLiteralTemp ("enum member");
10546 return cstring_makeLiteralTemp ("constant");
10548 if (uentry_isParam (ue))
10550 return cstring_makeLiteralTemp ("parameter");
10552 else if (uentry_isExpandedMacro (ue))
10554 return cstring_makeLiteralTemp ("expanded macro");
10558 return cstring_makeLiteralTemp ("variable");
10561 return cstring_makeLiteralTemp ("function");
10563 return cstring_makeLiteralTemp ("iterator");
10565 return cstring_makeLiteralTemp ("iterator finalizer");
10567 return cstring_makeLiteralTemp ("struct tag");
10569 return cstring_makeLiteralTemp ("union tag");
10571 return cstring_makeLiteralTemp ("enum tag");
10573 return cstring_makeLiteralTemp ("optional parameters");
10578 return cstring_makeLiteralTemp ("<Undefined>");
10584 void uentry_setHasNameError (uentry ue)
10586 llassert (uentry_isValid (ue));
10588 ue->hasNameError = TRUE;
10591 void uentry_checkName (uentry ue)
10593 DPRINTF (("Checking name: %s / %s / %s", uentry_unparse (ue),
10594 uentry_observeRealName (ue),
10595 bool_unparse (uentry_isVisibleExternally (ue))));
10597 if (uentry_isValid (ue)
10598 && !context_inXHFile ()
10599 && uentry_hasName (ue)
10600 && !uentry_isElipsisMarker (ue)
10601 && context_getFlag (FLG_NAMECHECKS)
10602 && !ue->hasNameError
10603 && !uentry_isEndIter (ue)
10604 && !fileloc_isBuiltin (uentry_whereLast (ue))
10605 && (uentry_isExpandedMacro (ue) || !uentry_isForward (ue)))
10607 DPRINTF (("Here..."));
10609 if (uentry_isPriv (ue))
10611 ; /* any checks here? */
10613 else if (fileloc_isExternal (uentry_whereDefined (ue)))
10615 ; /* no errors for externals */
10621 if (uentry_isExpandedMacro (ue))
10627 if (uentry_isExpandedMacro (ue))
10631 else if (uentry_isVariable (ue))
10633 sRef sr = uentry_getSref (ue);
10635 if (sRef_isValid (sr))
10637 scope = sRef_getScope (sr);
10644 else if (uentry_isFunction (ue)
10645 || uentry_isIter (ue)
10646 || uentry_isEndIter (ue)
10647 || uentry_isConstant (ue))
10649 scope = uentry_isStatic (ue) ? fileScope : globScope;
10651 else /* datatypes, etc. must be global */
10656 usymtab_checkDistinctName (ue, scope);
10659 if (context_getFlag (FLG_CPPNAMES))
10664 if (scope == globScope)
10666 checkExternalName (ue);
10668 else if (scope == fileScope)
10670 checkFileScopeName (ue);
10674 checkLocalName (ue);
10678 checkAnsiName (ue);
10683 /*@exposed@*/ uentry uentry_makeUnrecognized (cstring c, /*@keep@*/ fileloc loc)
10689 ** Can't but unrecognized ids in macros in global scope, because srefs will break! */
10690 if (!context_inMacro ())
10692 sRef_setGlobalScopeSafe ();
10695 ue = uentry_makeVariable (c, ctype_unknown, loc, FALSE);
10696 uentry_setUsed (ue, loc);
10698 tloc = fileloc_createExternal ();
10699 uentry_setDefined (ue, tloc);
10700 fileloc_free (tloc);
10701 uentry_setHasNameError (ue);
10703 if (context_getFlag (FLG_REPEATUNRECOG))
10705 uentry_markOwned (ue);
10709 ue = usymtab_supReturnFileEntry (ue);
10712 if (!context_inMacro ())
10714 sRef_clearGlobalScopeSafe ();
10720 uentry uentry_makeGlobalMarker ()
10725 llassert (sRef_inGlobalScope ());
10727 ue = uentry_makeVariableAux
10728 (GLOBAL_MARKER_NAME, ctype_unknown, fileloc_undefined,
10729 sRef_makeGlobalMarker (),
10732 tloc = fileloc_createExternal ();
10733 uentry_setUsed (ue, tloc);
10734 uentry_setDefined (ue, tloc);
10735 fileloc_free (tloc);
10736 uentry_setHasNameError (ue);
10742 bool uentry_isGlobalMarker (uentry ue)
10744 return (uentry_isValid (ue)
10745 && (cstring_equal (uentry_rawName (ue), GLOBAL_MARKER_NAME)));
10750 /* new start modifications */
10757 static void uentry_testInRange (uentry p_e, uentry cconstant) {
10758 if (uentry_isValid(p_e)) {
10759 if (sRef_isValid (p_e->sref)) {
10760 /* char * t = cstring_toCharsSafe (uentry_unparse(cconstant) );
10761 int index = atoi( t );
10764 long index = multiVal_forceInt (uentry_getConstantValue (cconstant));
10765 // usymtab_testInRange (p_e->sref, index);
10771 /* void uentry_setStringLength (uentry p_e, uentry cconstant) { */
10772 /* if( uentry_isValid(p_e) ) { */
10773 /* if( p_e->info != NULL) { */
10774 /* if( p_e->info->var != NULL) { */
10775 /* char *t = cstring_toCharsSafe (uentry_unparse(cconstant)); */
10776 /* int length = atoi( t ); */
10778 /* p_e->info->var->bufinfo->len = length; */
10779 /* p_e->sref->bufinfo.len = length; */
10780 /* printf("Set string length of buff to %d \n", p_e->sref->bufinfo.size); */
10787 static void uentry_setBufferSize (uentry p_e, exprNode cconstant) {
10788 if( uentry_isValid(p_e) ) {
10789 if( p_e->info != NULL) {
10790 if( p_e->info->var != NULL) {
10791 int size = atoi(cstring_toCharsSafe(exprNode_unparse(cconstant) ) );
10792 p_e->info->var->bufinfo->size = size;
10793 p_e->sref->bufinfo.size = size;
10794 printf("Set buffer size to %d \n", p_e->sref->bufinfo.size);
10795 // fprintf(stderr, "For %s and %s\n", uentry_unparse(p_e) );
10796 // fprintf(stderr, "and %d\n", size );
10806 /* start modifications */
10808 requires: p_e is defined, is a ptr/array variable
10810 effects: sets the state of the variable
10814 void uentry_setPossiblyNullTerminatedState (uentry p_e) {
10815 if( uentry_isValid(p_e) ) {
10816 if( p_e->info != NULL) {
10817 if( p_e->info->var != NULL) {
10818 p_e->info->var->bufinfo->bufstate = BB_POSSIBLYNULLTERMINATED;
10819 p_e->sref->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED;
10825 fprintf(stderr, "uentry:Error in setPossiblyNullTerminatedState\n");
10829 requires: p_e is defined, is a ptr/array variable
10831 effects: sets the size of the buffer
10834 void uentry_setNullTerminatedState (uentry p_e) {
10835 if( uentry_isValid(p_e) ) {
10836 if( p_e->info != NULL) {
10837 if( p_e->info->var != NULL) {
10838 p_e->info->var->bufinfo->bufstate = BB_NULLTERMINATED;
10839 p_e->sref->bufinfo.bufstate = BB_NULLTERMINATED;
10845 fprintf(stderr, "uentry:Error in setNullTerminatedState\n");
10850 requires: p_e is defined, is a ptr/array variable
10852 effects: sets the state of the variable
10855 /* void uentry_setNotNullTerminatedState (uentry p_e) { */
10856 /* if( uentry_isValid(p_e) ) { */
10857 /* if( p_e->info != NULL) { */
10858 /* if( p_e->info->var != NULL) { */
10859 /* p_e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED; */
10860 /* p_e->sref->bufinfo.bufstate = BB_NOTNULLTERMINATED; */
10866 /* fprintf(stderr, "uentry:Error in setNotNullTerminatedState\n"); */
10871 requires: p_e is defined, is a ptr/array variable
10873 effects: sets the size of the buffer
10876 void uentry_setSize (uentry p_e, int size) {
10877 if( uentry_isValid(p_e) ) {
10878 if( p_e->info != NULL) {
10879 if( p_e->info->var != NULL) {
10880 p_e->info->var->bufinfo->size = size;
10881 p_e->sref->bufinfo.size = size;
10887 fprintf(stderr, "uentry:Error in setSize\n");
10892 requires: p_e is defined, is a ptr/array variable
10894 effects: sets the length of the buffer
10897 void uentry_setLen (uentry p_e, int len) {
10898 if( uentry_isValid(p_e) ) {
10899 if( p_e->info != NULL) {
10900 if( p_e->info->var != NULL) {
10901 p_e->info->var->bufinfo->len = len;
10902 p_e->sref->bufinfo.len = len;
10908 fprintf(stderr, "uentry:Error in setLen\n");
10913 bool uentry_hasMetaStateEnsures (uentry e)
10915 if (uentry_isValid (e) && uentry_isFunction (e))
10917 return functionConstraint_hasMetaStateConstraint (e->info->fcn->postconditions);
10925 metaStateConstraint uentry_getMetaStateEnsures (uentry e)
10927 llassert (uentry_hasMetaStateEnsures (e));
10928 return functionConstraint_getMetaStateConstraint (e->info->fcn->postconditions);