2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
28 # include "splintMacros.nf"
30 # include "transferChecks.h"
46 static void checkStructTransfer (exprNode p_lhs, sRef p_slhs, exprNode p_rhs, sRef p_srhs,
47 fileloc p_loc, transferKind p_tt);
48 static void checkMetaStateConsistent (/*@exposed@*/ sRef p_fref, sRef p_tref,
49 fileloc p_loc, transferKind p_transferType) ;
51 static void checkLeaveTrans (uentry p_actual, transferKind p_transferType);
52 static void checkTransfer (exprNode p_fexp, /*@dependent@*/ sRef p_fref,
53 exprNode p_texp, /*@dependent@*/ sRef p_tref,
54 exprNode p_fcn, /* for printing better error messages */
55 fileloc p_loc, transferKind p_transferType);
56 static void checkGlobTrans (uentry p_glob, transferKind p_type);
59 checkCompletelyDefined (exprNode p_fexp, /*@exposed@*/ sRef p_fref, sRef p_ofref,
60 exprNode p_texp, sRef p_tref,
61 bool p_topLevel, bool p_inUnion, bool p_directUnion,
62 fileloc p_loc, transferKind p_transferType, int p_depth,
65 static /*@exposed@*/ sRef dependentReference (sRef p_sr);
66 static bool canLoseLocalReference (/*@dependent@*/ sRef p_sr, fileloc p_loc) ;
69 ** returns the most specific alkind
72 alkind alkind_resolve (alkind a1, alkind a2)
74 if (a1 == AK_UNKNOWN || a1 == AK_ERROR) return a2;
75 if (a2 == AK_UNKNOWN || a2 == AK_ERROR || a2 == AK_LOCAL) return a1;
76 if (a1 == AK_LOCAL) return a2;
84 ** FCNRETURN return fref; tref is return type
85 ** GLOBASSIGN tref = fref;
86 ** FCNPASS call (fref) ; tref is the argument type
90 static /*@only@*/ cstring
91 transferErrorMessage (transferKind transferType, alkind tkind) /*@*/
96 return (message ("returned as %s", alkind_unparse (tkind)));
98 return (message ("assigned to %s", alkind_unparse (tkind)));
100 return (message ("assigned to %s", alkind_unparse (tkind)));
102 return (message ("used as initial value for %s",
103 alkind_unparse (tkind)));
105 return (message ("passed as %s param", alkind_unparse (tkind)));
111 static /*@only@*/ cstring
112 transferErrorExcerpt (transferKind transferType, exprNode fexp, exprNode texp, exprNode fcn) /*@*/
114 switch (transferType)
117 return (message ("return %s", exprNode_unparse (fexp)));
121 return (message ("%s = %s", exprNode_unparse (texp), exprNode_unparse (fexp)));
123 if (exprNode_isDefined (fcn))
125 return message ("%s(..., %s, ...)",
126 exprNode_unparse (fcn),
127 exprNode_unparse (fexp));
131 return cstring_copy (exprNode_unparse (fexp));
139 transferErrorExpMessage (transferKind transferType, exkind tkind) /*@*/
141 if (exkind_isUnknown (tkind))
143 switch (transferType)
146 return (cstring_makeLiteral ("returned without qualification"));
149 return (cstring_makeLiteral ("assigned to unqualified reference"));
151 return (cstring_makeLiteral ("passed without qualification"));
153 return (cstring_makeLiteral ("used as initial value for unqualified storage"));
159 switch (transferType)
162 return (message ("returned as %s", exkind_unparse (tkind)));
165 return (message ("assigned to %s", exkind_unparse (tkind)));
167 return (message ("passed as %s param", exkind_unparse (tkind)));
175 static /*@observer@*/ cstring
176 transferNullMessage (transferKind transferType) /*@*/
178 switch (transferType)
181 return (cstring_makeLiteralTemp ("returned as non-null"));
184 return (cstring_makeLiteralTemp ("assigned to non-null"));
186 return (cstring_makeLiteralTemp ("initialized to non-null"));
188 return (cstring_makeLiteralTemp ("passed as non-null param"));
194 static /*@dependent@*/ exprNode atFunction = exprNode_undefined;
195 static int atArgNo = 0;
196 static int atNumArgs = 0;
198 static cstring generateText (exprNode e1, exprNode e2,
199 sRef tref, transferKind tt)
202 if (tt == TT_DOASSIGN || tt == TT_GLOBINIT)
204 return (message ("%s = %s", exprNode_unparse (e2),
205 exprNode_unparse (e1)));
207 else if (tt == TT_FIELDASSIGN)
209 return (message ("%s = %s (field %q)",
210 exprNode_unparse (e2),
211 exprNode_unparse (e1),
212 sRef_unparse (tref)));
214 else if (tt == TT_FCNPASS)
216 return (message ("%s (%s%s%s)",
217 exprNode_unparse (atFunction),
218 (atArgNo == 1 ? cstring_undefined
219 : cstring_makeLiteralTemp ("..., ")),
220 exprNode_unparse (e1),
221 (atArgNo == atNumArgs ? cstring_undefined
222 : cstring_makeLiteralTemp (", ..."))));
226 return (cstring_copy (exprNode_unparse (e1)));
230 static /*@observer@*/ cstring
231 transferType_unparse (transferKind transferType) /*@*/
233 switch (transferType)
236 return (cstring_makeLiteralTemp ("Returned"));
239 return (cstring_makeLiteralTemp ("Assigned"));
241 return (cstring_makeLiteralTemp ("Passed"));
243 return (cstring_makeLiteralTemp ("Initialized"));
245 return (cstring_makeLiteralTemp ("GLOB RETURN!"));
247 return (cstring_makeLiteralTemp ("GLOB PASS!"));
249 return (cstring_makeLiteralTemp ("PARAM RETURN!"));
251 return (cstring_makeLiteralTemp ("LEAVE TRANS!"));
257 static /*@observer@*/ cstring udError (sRef s)
261 return cstring_makeLiteralTemp ("released");
263 else if (sRef_isAllocated (s))
265 return cstring_makeLiteralTemp ("allocated but not defined");
269 return cstring_makeLiteralTemp ("undefined");
274 cstring defExpl (sRef s) /*@*/
276 sRef rb = sRef_getRootBase (s);
278 if (sRef_sameName (rb, s))
280 if (sRef_isAllocated (s))
282 return cstring_makeLiteral (" (allocated only)");
284 return cstring_undefined;
288 return (message (" (%q is %s)", sRef_unparse (s), udError (s)));
294 ** More than just definition checking --- checks for consistent state also!
296 ** Returns TRUE if fref is completely defined.
297 ** if !report, returns TRUE unless error is at the deep level.
301 checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
302 exprNode texp, sRef tref,
303 bool topLevel, bool inUnion, bool directUnion,
304 fileloc loc, transferKind transferType,
305 int depth, bool report)
308 alkind fkind = sRef_getAliasKind (fref);
309 alkind tkind = sRef_getAliasKind (tref);
311 DPRINTF (("Check completely defined: %s [%s] / %s [%s]",
312 exprNode_unparse (fexp), sRef_unparseFull (fref),
313 exprNode_unparse (texp), sRef_unparseFull (tref)));
315 if (depth > MAXDEPTH)
319 ("Check definition limit exceeded, checking %q. "
320 "This either means there is a variable with at least "
321 "%d indirections apparent in the program text, or "
322 "there is a bug in Splint.",
329 if (!sRef_isKnown (fref))
334 if (sRef_isDead (fref))
336 DPRINTF (("Dead storage to completely defined: %s", sRef_unparseFull (fref)));
339 if (alkind_isStack (fkind))
341 ctype rt = ctype_realType (sRef_getType (tref));
343 if (ctype_isMutable (rt) && !ctype_isSU (rt))
345 if (transferType == TT_PARAMRETURN)
350 ("Stack-allocated storage %qreachable from parameter %q",
351 sRef_unparseOpt (fref),
352 sRef_unparse (ofref)),
355 sRef_showAliasInfo (fref);
358 else if (transferType == TT_GLOBRETURN)
363 ("Stack-allocated storage %qreachable from global %q",
364 sRef_unparseOpt (fref),
365 sRef_unparse (ofref)),
368 sRef_showAliasInfo (fref);
371 else if (transferType == TT_FCNRETURN)
376 ("Stack-allocated storage %qreachable from return value: %s",
377 sRef_unparseOpt (fref),
378 exprNode_unparse (fexp)),
381 sRef_showAliasInfo (fref);
393 DPRINTF (("From: %s ==> %s",
394 sRef_unparseFull (fref),
395 sRef_unparseFull (tref)));
397 checkMetaStateConsistent (fref, tref, loc, transferType);
399 if ((sRef_isObserver (fref) && !sRef_isObserver (tref))
400 || (sRef_isExposed (fref) && !(sRef_isObserver (tref)
401 || sRef_isExposed (tref))))
403 flagcode code = (sRef_isObserver (fref)
404 ? FLG_OBSERVERTRANS : FLG_EXPOSETRANS);
406 if (!sRef_isStateLive (fref))
408 ; /* no error (will be a definition error) */
410 else if (transferType == TT_DOASSIGN
411 || transferType == TT_FIELDASSIGN
412 || transferType == TT_GLOBINIT
413 || transferType == TT_FCNPASS)
417 else if (transferType == TT_PARAMRETURN)
422 ("%s storage %qreachable from %s parameter",
423 exkind_capName (sRef_getExKind (fref)),
424 sRef_unparseOpt (fref),
425 exkind_unparseError (sRef_getExKind (tref))),
428 sRef_showExpInfo (fref);
429 sRef_setExKind (fref, XO_UNKNOWN, loc);
432 else if (transferType == TT_LEAVETRANS)
436 else if (transferType == TT_GLOBINIT)
441 ("%s storage %qreachable from %s initial value",
442 exkind_capName (sRef_getExKind (fref)),
443 sRef_unparseOpt (fref),
444 exkind_unparseError (sRef_getExKind (tref))),
447 sRef_showExpInfo (fref);
448 sRef_setExKind (fref, XO_UNKNOWN, loc);
451 else if (transferType == TT_GLOBRETURN)
456 ("%s storage %qreachable from %s global",
457 exkind_capName (sRef_getExKind (fref)),
458 sRef_unparseOpt (fref),
459 exkind_unparseError (sRef_getExKind (tref))),
462 sRef_showExpInfo (fref);
463 sRef_setExKind (fref, XO_UNKNOWN, loc);
466 else if (transferType == TT_FCNRETURN)
471 ("%s storage %qreachable from %s return value",
472 exkind_capName (sRef_getExKind (fref)),
473 sRef_unparseOpt (fref),
474 exkind_unparseError (sRef_getExKind (tref))),
477 sRef_showExpInfo (fref);
478 sRef_setExKind (fref, XO_UNKNOWN, loc);
483 llcontbug (message ("Transfer type: %s",
484 transferType_unparse (transferType)));
489 ("%s storage %qreachable from %s return value",
490 exkind_capName (sRef_getExKind (fref)),
491 sRef_unparseOpt (fref),
492 exkind_unparseError (sRef_getExKind (tref))),
495 sRef_showExpInfo (fref);
496 sRef_setExKind (fref, XO_UNKNOWN, loc);
502 if (!alkind_compatible (fkind, tkind))
504 if (fkind == AK_UNKNOWN && !sRef_isStateLive (fref))
506 ; /* no error (will be a definition error) */
508 else if (transferType == TT_DOASSIGN
509 || transferType == TT_FIELDASSIGN) /* evans 2002-02-05 - added TT_FIELDASSIGN */
513 else if (transferType == TT_FCNPASS)
515 if (alkind_isKnown (sRef_getAliasKind (tref)))
520 ("Storage %qreachable from passed parameter "
521 "is %s (should be %s): %s",
522 sRef_unparseOpt (fref),
523 alkind_unparse (sRef_getAliasKind (fref)),
524 alkind_unparse (sRef_getAliasKind (tref)),
525 exprNode_unparse (fexp)),
528 sRef_showAliasInfo (fref);
532 else if (transferType == TT_PARAMRETURN)
534 bool noerror = FALSE;
536 if (alkind_isDependent (sRef_getAliasKind (fref)))
538 if (canLoseLocalReference (fref, loc))
548 ("Storage %qreachable from parameter is %s (should be %s)",
549 sRef_unparseOpt (fref),
550 alkind_unparse (sRef_getAliasKind (fref)),
551 alkind_unparse (sRef_getAliasKind (tref))),
554 sRef_showAliasInfo (fref);
557 else if (transferType == TT_LEAVETRANS)
562 ("Storage %qreachable from temporary reference is %s "
563 "at scope exit (should be %s)",
564 sRef_unparseOpt (fref),
565 alkind_unparse (sRef_getAliasKind (fref)),
566 alkind_unparse (sRef_getAliasKind (tref))),
569 sRef_showAliasInfo (fref);
572 else if (transferType == TT_GLOBRETURN)
577 ("Storage %qreachable from global is %s (should be %s)",
578 sRef_unparseOpt (fref),
579 alkind_unparse (sRef_getAliasKind (fref)),
580 alkind_unparse (sRef_getAliasKind (tref))),
583 sRef_showAliasInfo (fref);
586 else if (transferType == TT_FCNRETURN)
591 ("Storage %qreachable from return value is %s (should be %s)",
592 sRef_unparseOpt (fref),
593 alkind_unparse (sRef_getAliasKind (fref)),
594 alkind_unparse (sRef_getAliasKind (tref))),
597 sRef_showAliasInfo (fref);
600 else if (transferType == TT_GLOBINIT)
605 ("Storage %qreachable from initial value is %s (should be %s)",
606 sRef_unparseOpt (fref),
607 alkind_unparse (sRef_getAliasKind (fref)),
608 alkind_unparse (sRef_getAliasKind (tref))),
611 sRef_showAliasInfo (fref);
616 llcontbug (message ("Transfer type: %s",
617 transferType_unparse (transferType)));
622 ("Storage %qreachable from return value is %s (should be %s)",
623 sRef_unparseOpt (fref),
624 alkind_unparse (sRef_getAliasKind (fref)),
625 alkind_unparse (sRef_getAliasKind (tref))),
628 sRef_showAliasInfo (fref);
633 if (sRef_isDead (fref))
640 if (transferType == TT_PARAMRETURN)
645 ("Released storage %q reachable from parameter at return point",
646 sRef_unparse (fref)),
649 sRef_showStateInfo (fref);
653 else if (transferType == TT_LEAVETRANS)
657 message ("Released storage %q reachable from temporary "
658 "reference at scope exit",
659 sRef_unparse (fref)),
662 sRef_showStateInfo (fref);
666 else if (transferType == TT_GLOBRETURN)
670 message ("Released storage %q reachable from global",
671 sRef_unparse (fref)),
674 sRef_showStateInfo (fref);
678 else if (transferType == TT_FCNPASS)
682 message ("Released storage %q reachable from passed parameter",
683 sRef_unparse (fref)),
686 sRef_showStateInfo (fref);
694 message ("Released storage %q reachable from parameter",
695 sRef_unparse (fref)),
698 sRef_showStateInfo (fref);
706 && sRef_possiblyNull (fref)
707 && !sRef_perhapsNull (tref)
708 && ctype_isRealPointer (sRef_getType (tref))
709 && !usymtab_isGuarded (fref))
711 if (transferType == TT_FCNRETURN)
715 message ("%q storage %qderivable from return value: %s",
716 cstring_capitalize (sRef_nullMessage (fref)),
717 sRef_unparseOpt (fref),
718 exprNode_unparse (fexp)),
721 sRef_showNullInfo (fref);
723 DPRINTF (("fref: %s", sRef_unparseFull (fref)));
724 DPRINTF (("tref: %s", sRef_unparseFull (tref)));
726 sRef_setNullError (fref);
729 else if (transferType == TT_GLOBRETURN || transferType == TT_PARAMRETURN)
734 ("Function returns with %s storage derivable from %q %q",
735 sRef_nullMessage (fref),
736 cstring_makeLiteral ((transferType == TT_GLOBRETURN)
737 ? "global" : "parameter"),
738 sRef_unparse (fref)),
741 sRef_showNullInfo (fref);
742 sRef_setNullError (fref);
745 else if (transferType == TT_GLOBPASS)
749 message ("Function called with %s storage "
750 "derivable from global %q",
751 sRef_nullMessage (fref),
752 sRef_unparse (fref)),
755 sRef_showNullInfo (fref);
756 sRef_setNullError (fref);
759 else if (transferType == TT_FCNPASS)
763 message ("%q storage %qderivable from parameter %q",
764 cstring_capitalize (sRef_nullMessage (fref)),
765 sRef_unparseOpt (fref),
766 generateText (fexp, exprNode_undefined,
767 sRef_undefined, TT_FCNPASS)),
770 DPRINTF (("fref: %s", sRef_unparseFull (fref)));
771 DPRINTF (("tref: %s", sRef_unparseFull (tref)));
772 sRef_showNullInfo (fref);
773 sRef_setNullError (fref);
778 llassert (transferType == TT_DOASSIGN
779 || transferType == TT_FIELDASSIGN /* evans 2002-02-05: no warnings for local fields */
780 || transferType == TT_GLOBINIT
781 || transferType == TT_LEAVETRANS);
785 if (sRef_isRelDef (tref)
786 || sRef_isPartial (tref)
787 || sRef_isAllocated (tref)
788 || sRef_isStateSpecial (tref))
790 /* should check fref is allocated? */
794 ct = ctype_realType (sRef_getType (fref));
796 DPRINTF (("Here: %s", ctype_unparse (ct)));
798 if (!(sRef_isAnyDefined (fref)
799 || sRef_isPdefined (fref)
800 || sRef_isAllocated (fref)
801 || sRef_isStateUnknown (fref)))
803 if (transferType == TT_GLOBRETURN)
808 message ("Function returns with global %q not "
809 "completely defined%q",
810 sRef_unparse (sRef_getRootBase (fref)),
814 sRef_showStateInfo (fref);
815 sRef_setDefined (fref, loc);
818 else if (transferType == TT_GLOBPASS)
824 ("Function called with global %q not completely defined%q",
825 sRef_unparse (sRef_getRootBase (fref)),
829 sRef_showStateInfo (fref);
830 sRef_setDefined (fref, loc);
833 else if (transferType == TT_PARAMRETURN)
835 if (report && !topLevel
838 message ("Function returns storage %q reachable from parameter not "
839 "completely defined%q",
840 sRef_unparse (ofref),
844 sRef_showStateInfo (fref);
845 sRef_setDefined (fref, loc);
848 else if (transferType == TT_LEAVETRANS)
850 if (report && !topLevel
853 message ("Scope exits with storage %q reachable from "
854 "temporary reference not completely defined%q",
855 sRef_unparse (ofref),
859 sRef_showStateInfo (fref);
860 sRef_setDefined (fref, loc);
865 if (transferType != TT_DOASSIGN
866 && (!(sRef_isNew (fref) || sRef_isType (fref))))
870 DPRINTF (("Here we are: %s", sRef_unparseFull (fref)));
872 if (sRef_isDead (fref))
876 message ("%s storage %qwas released: %q",
877 transferType_unparse (transferType),
878 sRef_unparseOpt (fref),
879 generateText (fexp, texp, tref, transferType)),
882 sRef_showStateInfo (fref);
890 ("%s storage %qnot completely defined%q: %q",
891 transferType_unparse (transferType),
892 sRef_unparseOpt (ofref),
894 generateText (fexp, texp, tref, transferType)),
897 sRef rb = sRef_getRootBase (fref);
898 sRef_showStateInfo (fref);
900 sRef_setDefinedCompleteDirect (rb, loc);
908 if (sRef_isAllocated (fref) && sRef_isValid (tref)
909 && (transferType == TT_DOASSIGN))
911 sRef_setAllocatedComplete (tref, loc);
920 if (ctype_isUnknown (ct))
924 else if (ctype_isPointer (ct) || ctype_isArray (ct)) /* evans 2001-07-12 added ctype_isArray */
926 ctype tct = ctype_realType (sRef_getType (tref));
928 if (sRef_isStateUnknown (fref))
934 DPRINTF (("Here fref: %s", sRef_unparseFull (fref)));
935 DPRINTF (("Here tref: %s", sRef_unparseFull (tref)));
937 if (ctype_isAP (tct) || ctype_isUnknown (tct))
939 sRef fptr = sRef_constructDeref (fref);
940 sRef tptr = sRef_constructDeref (tref);
942 DPRINTF (("Here tptr: %s", sRef_unparseFull (tptr)));
944 return (checkCompletelyDefined (fexp, fptr, ofref,
946 FALSE, inUnion, FALSE, loc,
947 transferType, depth + 1, report));
955 else if (ctype_isStruct (ct))
957 ctype tct = ctype_realType (sRef_getType (tref));
959 DPRINTF (("Struct defined: %s", ctype_unparse (tct)));
961 if (ctype_match (ct, tct))
964 bool hasOneDefined = FALSE;
965 cstringSList badFields = cstringSList_undefined;
967 if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref))
972 DPRINTF (("Check field: %s", sRef_unparseFull (fref)));
974 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
976 DPRINTF (("Is defined: %s", sRef_unparse (fref)));
978 sRefSet_realElements (sRef_derivedFields (fref), sr)
982 hasOneDefined = TRUE;
984 DPRINTF (("Check derived: %s", sRef_unparseFull (sr)));
986 if (sRef_isField (sr))
988 cstring fieldname = sRef_getField (sr);
989 sRef fldref = sRef_makeField (tref, fieldname);
990 bool shouldCheck = !sRef_isRecursiveField (fldref);
996 (checkCompletelyDefined (fexp, sr, ofref,
998 FALSE, inUnion, FALSE, loc,
999 transferType, depth + 1,
1010 badFields = cstringSList_add (badFields,
1011 sRef_getField (sr));
1014 } end_sRefSet_realElements;
1016 else if (sRef_isAllocated (fref))
1019 ** for structures, each field must be completely defined
1022 uentryList fields = ctype_getFields (ct);
1024 uentryList_elements (fields, ue)
1027 cstring name = uentry_getRealName (ue);
1028 sRef ffield = sRef_makeField (fref, name);
1029 sRef tfield = sRef_makeField (tref, name);
1030 bool shouldCheck = !sRef_isRecursiveField (tfield);
1038 thisField = ynm_toBoolRelaxed
1039 (checkCompletelyDefined (fexp, ffield, ofref,
1041 FALSE, inUnion, FALSE,
1049 badFields = cstringSList_add (badFields, uentry_rawName (ue));
1053 hasOneDefined = TRUE;
1055 } end_uentryList_elements;
1059 DPRINTF (("Not checking: %s", sRef_unparseFull (fref)));
1062 if (!isOk && (!inUnion || hasOneDefined))
1064 if (transferType == TT_GLOBRETURN)
1068 message ("Global storage %q contains %d undefined field%& "
1069 "when call returns: %q",
1070 sRef_unparse (fref),
1071 cstringSList_size (badFields),
1072 cstringSList_unparseAbbrev (badFields)),
1075 sRef_setDefined (fref, loc);
1078 else if (transferType == TT_GLOBPASS)
1082 message ("Global storage %q contains %d undefined field%& "
1084 sRef_unparse (fref),
1085 cstringSList_size (badFields),
1086 cstringSList_unparseAbbrev (badFields)),
1089 sRef_setDefined (fref, loc);
1092 else if (transferType == TT_PARAMRETURN)
1096 message ("Storage %qreachable from parameter "
1097 "contains %d undefined field%&: %q",
1098 sRef_unparseOpt (fref),
1099 cstringSList_size (badFields),
1100 cstringSList_unparseAbbrev (badFields)),
1103 sRef_setDefined (fref, loc);
1106 else if (transferType == TT_LEAVETRANS)
1114 message ("%s storage %qcontains %d undefined field%&: %q",
1115 transferType_unparse (transferType),
1116 sRef_unparseOpt (fref),
1117 cstringSList_size (badFields),
1118 cstringSList_unparseAbbrev (badFields)),
1121 sRef_setDefined (fref, loc);
1126 cstringSList_free (badFields);
1132 return (ynm_fromBool (hasOneDefined));
1141 return (ynm_fromBool (!report || isOk));
1149 else if (ctype_isUnion (ct))
1151 if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref))
1157 ctype tct = ctype_realType (sRef_getType (tref));
1159 if (ctype_isKnown (tct) && ctype_match (ct, tct))
1161 cstringSList goodFields = cstringSList_new ();
1163 int nelements = sRefSet_size (sRef_derivedFields (fref));
1166 ** for unions, at least one field must be completely defined
1169 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
1174 sRefSet_realElements (sRef_derivedFields (fref), sr)
1178 if (sRef_isField (sr))
1180 sRef fldref = sRef_makeField (tref, sRef_getField (sr));
1182 DPRINTF (("Trying union field: %s", sRef_unparseFull (fldref)));
1184 thisField = ynm_toBoolStrict
1185 (checkCompletelyDefined
1187 texp, fldref, FALSE, inUnion,
1188 (nelements > 1 ? TRUE : FALSE),
1189 loc, transferType, depth + 1, FALSE));
1193 goodFields = cstringSList_add
1194 (goodFields, sRef_getField (sr));
1197 } end_sRefSet_realElements;
1199 if (cstringSList_empty (goodFields)
1201 && context_getFlag (FLG_UNIONDEF))
1205 if (transferType == TT_PARAMRETURN)
1209 message ("Union %q reachable from parameter has "
1211 sRef_unparse (fref)),
1214 else if (transferType == TT_LEAVETRANS)
1218 message ("Union %q has no defined field at scope exit",
1219 sRef_unparse (fref)),
1222 /* evans 2001-08-21: added this branch for global returns */
1223 else if (transferType == TT_GLOBRETURN)
1227 message ("Union %q reachable from global %q has "
1229 sRef_unparse (fref),
1230 sRef_unparse (sRef_getRootBase (fref))),
1233 else if (transferType == TT_DOASSIGN
1234 || transferType == TT_FIELDASSIGN
1235 || transferType == TT_GLOBINIT)
1243 message ("%s union %q has no defined field",
1244 transferType_unparse (transferType),
1245 sRef_unparse (fref)),
1252 cstringSList_free (goodFields);
1253 return ynm_fromBool (!report || isOk);
1266 ** fref is being free'd
1270 DSC_GLOB, DSC_LOCAL, DSC_PARAM, DSC_STRUCT
1273 static /*@observer@*/ cstring dscCode_unparse (dscCode desc) /*@*/
1278 return cstring_makeLiteralTemp ("killed global");
1280 return cstring_makeLiteralTemp ("variable declared in this scope");
1282 return cstring_makeLiteralTemp ("released storage");
1284 return cstring_makeLiteralTemp ("released structure parameter");
1291 checkCompletelyDestroyed (exprNode p_fexp, sRef p_fref, bool p_topLevel, bool p_isField,
1292 fileloc p_loc, int p_depth, dscCode p_desc,
1295 bool transferChecks_globalDestroyed (sRef fref, fileloc loc)
1297 DPRINTF (("Global destroyed: %s", sRef_unparseFull (fref)));
1298 return (checkCompletelyDestroyed (exprNode_undefined, fref, TRUE, FALSE,
1299 loc, 0, DSC_GLOB, FALSE));
1302 void transferChecks_localDestroyed (sRef fref, fileloc loc)
1304 if (sRef_isObserver (fref) || sRef_isExposed (fref)
1305 || sRef_isPartial (fref))
1311 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE, FALSE,
1312 loc, 0, DSC_LOCAL, FALSE);
1316 void transferChecks_structDestroyed (sRef fref, fileloc loc)
1318 DPRINTF (("Check struct destroyed: %s", sRef_unparse (fref)));
1320 if (sRef_isObserver (fref) || sRef_isExposed (fref)
1321 || sRef_isPartial (fref))
1323 DPRINTF (("Its exposed!"));;
1327 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE, FALSE,
1328 loc, 0, DSC_STRUCT, FALSE);
1333 checkCompletelyDestroyed (exprNode fexp, sRef fref, bool topLevel, bool isField,
1334 fileloc loc, int depth,
1335 dscCode desc, bool hideErrors)
1339 DPRINTF (("Check completely destroyed: %s / %s",
1340 sRef_unparse (fref),
1341 bool_unparse (hideErrors)));
1343 if (depth > MAXDEPTH)
1345 llquietbug (message ("checkCompletelyDestroyed: too deep: %s / %q",
1346 exprNode_unparse (fexp),
1347 sRef_unparseFull (fref)));
1351 if (!sRef_isKnown (fref)) return TRUE;
1353 /* evans 2001-03-24: added this. Definitely null values are always destroyed. */
1355 if (sRef_isDefinitelyNull (fref))
1360 if (sRef_isDependent (fref) || sRef_isShared (fref) || sRef_isKept (fref))
1367 ** evans 2001-03-24: if there is a dependent reference to this storage,
1368 ** no need to destroy, but make it responsible.
1371 sRef depRef = dependentReference (fref);
1373 DPRINTF (("Destroyed? %s / %s",
1374 sRef_unparseFull (fref),
1375 sRef_unparseFull (depRef)));
1377 DPRINTF (("Aliases: %s", usymtab_unparseAliases ()));
1379 if (sRef_isValid (depRef))
1382 ** If the referenced storage was not dependent, we make
1383 ** the reference the owner since it must eventually be
1387 if (!sRef_isDependent (depRef))
1389 sRef_setOnly (depRef, loc); /* could be owned? */
1392 sRef_kill (fref, loc);
1397 ct = ctype_realType (sRef_getType (fref));
1399 if (sRef_isPdefined (fref)
1402 && !context_getFlag (FLG_STRICTDESTROY))
1405 ** Don't report errors for array elements (unless strictdestroy)
1406 ** when at least one appears to have been destroyed.
1409 DPRINTF (("Partial: %s / hiding errors: %s", sRef_unparseFull (fref),
1410 ctype_unparse (ct)));
1412 /* Don't report any more errors, but still change ownership. */
1415 if (usymtab_isDefinitelyNull (fref))
1417 DPRINTF (("Probably null!"));
1422 ** evans 2002-01-02: removed this
1423 ** if (!context_flagOn (FLG_COMPDESTROY, loc))
1428 ** if (!context_getFlag (FLG_MUSTFREEONLY)) return TRUE;
1431 DPRINTF (("Here: %s", ctype_unparse (ct)));
1435 bool docheck = FALSE;
1438 if (sRef_isFresh (fref) || sRef_isOnly (fref))
1442 DPRINTF (("Here: %s", ctype_unparse (ct)));
1443 if (sRef_isDead (fref)
1444 || sRef_isUnuseable (fref)
1445 || sRef_definitelyNull (fref)
1446 || sRef_isObserver (fref)
1447 || sRef_isExposed (fref))
1455 if (sRef_isPossiblyDead (fref) || sRef_isRelDef (fref))
1457 if (exprNode_isDefined (fexp))
1463 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1464 message ("Only storage %q (type %s) derived from %s "
1465 "may not have been released: %s",
1466 sRef_unparse (fref),
1467 ctype_unparse (sRef_getType (fref)),
1468 dscCode_unparse (desc),
1469 exprNode_unparse (fexp)),
1478 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1480 ("Only storage %q (type %s) derived from %s "
1481 "may not have been released",
1482 sRef_unparse (fref),
1483 ctype_unparse (sRef_getType (fref)),
1484 dscCode_unparse (desc)),
1490 sRef_kill (fref, loc); /* prevent further errors */
1495 if (sRef_isStateUndefined (fref))
1497 DPRINTF (("Here: %s", ctype_unparse (ct)));
1502 if (exprNode_isDefined (fexp))
1504 DPRINTF (("Here: %s", sRef_unparseFull (fref)));
1511 message ("Only storage %q (type %s) derived from %s "
1512 "is not released (memory leak): %s",
1513 sRef_unparse (fref),
1514 ctype_unparse (sRef_getType (fref)),
1515 dscCode_unparse (desc),
1516 exprNode_unparse (fexp)),
1526 message ("Only storage %q (type %s) derived from %s "
1527 "is not released (memory leak)",
1528 sRef_unparse (fref),
1529 ctype_unparse (sRef_getType (fref)),
1530 dscCode_unparse (desc)),
1538 /* sRef_kill (fref, loc); */ /* prevent further errors */
1539 DPRINTF (("Killed: %s", sRef_unparseFull (fref)));
1544 DPRINTF (("Here: %s", ctype_unparse (ct)));
1548 if (/*! evs-2002-03-24 sRef_isAnyDefined (fref) || */
1550 || (sRef_isPdefined (fref)
1551 && sRefSet_isEmpty (sRef_derivedFields (fref))))
1553 DPRINTF (("Here: %s [%s / %s]",
1554 sRef_unparseFull (fref),
1555 bool_unparse (sRef_isAnyDefined (fref)),
1556 bool_unparse (sRef_isDead (fref))));
1561 DPRINTF (("Here..."));
1563 if (ctype_isPointer (ct))
1565 sRef fptr = sRef_constructDeadDeref (fref);
1568 res = checkCompletelyDestroyed (fexp, fptr, FALSE, FALSE,
1569 loc, depth + 1, desc, hideErrors);
1573 else if (ctype_isArray (ct))
1575 if ((sRef_isStateUnknown (fref) || sRef_isAllocated (fref))
1576 && !sRef_hasDerived (fref))
1579 ** Bogosity necessary to prevent infinite depth.
1586 sRef farr = sRef_constructDeadDeref (fref);
1588 return (checkCompletelyDestroyed (fexp, farr, FALSE, FALSE,
1589 loc, depth + 1, desc, hideErrors));
1592 else if (ctype_isStruct (ct))
1595 ** for structures, each field must be completely destroyed
1599 uentryList fields = ctype_getFields (ct);
1601 DPRINTF (("Struct fields: %s", uentryList_unparse (fields)));
1603 if (depth >= MAXDEPTH)
1605 llquietbug (message ("checkCompletelyDestroyed (fields): too deep: %s / %q",
1606 exprNode_unparse (fexp),
1607 sRef_unparseFull (fref)));
1613 uentryList_elements (fields, ue)
1615 sRef field = sRef_makeField (fref, uentry_rawName (ue));
1618 ** note order of && operands --- want to report multiple errors
1621 DPRINTF (("Check field: %s", sRef_unparseFull (field)));
1623 isOk = (checkCompletelyDestroyed (fexp, field, FALSE, TRUE,
1624 loc, depth + 1, desc, hideErrors)
1626 } end_uentryList_elements;
1638 transferChecks_return (exprNode fexp, uentry rval)
1640 sRef uref = uentry_getSref (rval);
1641 sRef rref = sRef_makeNew (sRef_getType (uref), uref, cstring_undefined);
1642 uentry fcn = context_getHeader ();
1643 sRef fref = exprNode_getSref (fexp);
1644 stateClauseList clauses = uentry_getStateClauseList (fcn);
1646 DPRINTF (("Check return: %s as %s = %s",
1647 exprNode_unparse (fexp),
1648 sRef_unparseFull (uref),
1649 sRef_unparseFull (rref)));
1651 /* evans 2001-07-18: removed: if (sRef_isStateSpecial (rref)) */
1653 DPRINTF (("Check state clauses: %s",
1654 stateClauseList_unparse (clauses)));
1656 stateClauseList_postElements (clauses, cl)
1658 if (stateClause_isGlobal (cl))
1662 else if (stateClause_setsMetaState (cl))
1664 sRefSet refs = stateClause_getRefs (cl);
1665 qual ql = stateClause_getMetaQual (cl);
1666 annotationInfo ainfo = qual_getAnnotationInfo (ql);
1667 metaStateInfo minfo = annotationInfo_getState (ainfo);
1668 cstring key = metaStateInfo_getName (minfo);
1669 int mvalue = annotationInfo_getValue (ainfo);
1671 DPRINTF (("Return check: %s", stateClause_unparse (cl)));
1673 sRefSet_elements (refs, el)
1675 sRef base = sRef_getRootBase (el);
1677 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
1679 if (sRef_isResult (base))
1681 sRef sr = sRef_fixBase (el, fref);
1683 if (!sRef_checkMetaStateValue (sr, key, mvalue))
1687 message ("Result state %q does not satisfy ensures "
1688 "clause: %q (state is %q, should be %s): %s",
1690 stateClause_unparse (cl),
1691 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
1693 metaStateInfo_unparseValue (minfo, mvalue),
1694 exprNode_unparse (fexp)),
1695 exprNode_loc (fexp)))
1697 sRef_showAliasInfo (sr);
1705 ** Non-results are checked in exit scope.
1708 } end_sRefSet_elements ;
1712 sRefSet refs = stateClause_getRefs (cl);
1713 sRefTest tst = stateClause_getPostTestFunction (cl);
1714 sRefMod modf = stateClause_getReturnEffectFunction (cl);
1716 DPRINTF (("Clause: %s / %s",
1717 stateClause_unparse (cl),
1718 sRefSet_unparse (refs)));
1720 sRefSet_elements (refs, el)
1722 sRef base = sRef_getRootBase (el);
1724 DPRINTF (("el: %s / %s", sRef_unparse (el),
1725 sRef_unparse (base)));
1727 if (sRef_isResult (base)
1728 && !sRef_isDefinitelyNull (fref)) /* evans 2002-07-22: don't report allocation errors for null results */
1730 sRef sr = sRef_fixBase (el, fref);
1732 if (tst != NULL && !(tst (sr)))
1735 (stateClause_postErrorCode (cl),
1736 message ("%s storage %q corresponds to "
1737 "storage %q listed in %q clause: %s",
1738 stateClause_postErrorString (cl, sr),
1741 stateClause_unparseKind (cl),
1742 exprNode_unparse (fexp)),
1743 exprNode_loc (fexp)))
1745 sRefShower ss = stateClause_getPostTestShower (cl);
1756 modf (sr, exprNode_loc (fexp));
1762 ** Non-results are checked in exit scope.
1765 } end_sRefSet_elements ;
1767 } end_stateClauseList_postElements ;
1769 if (ctype_isRealSU (exprNode_getType (fexp)))
1771 sRef ffref = exprNode_getSref (fexp);
1773 checkStructTransfer (exprNode_undefined, rref,
1775 exprNode_loc (fexp),
1780 (void) checkTransfer (fexp, exprNode_getSref (fexp),
1781 exprNode_undefined, rref,
1783 exprNode_loc (fexp), TT_FCNRETURN);
1788 checkPassstateClauseList (uentry ue, exprNode fexp, sRef fref, int argno)
1790 stateClauseList clauses = uentry_getStateClauseList (ue);
1792 DPRINTF (("Check pass special: %s / %s",
1793 exprNode_unparse (fexp), sRef_unparseFull (fref)));
1795 stateClauseList_preElements (clauses, cl)
1797 if (stateClause_isGlobal (cl))
1803 sRefSet refs = stateClause_getRefs (cl);
1804 sRefTest tst = stateClause_getPreTestFunction (cl);
1805 sRefMod modf = stateClause_getEffectFunction (cl);
1807 sRefSet_elements (refs, el)
1809 sRef base = sRef_getRootBase (el);
1811 if (sRef_isResult (base))
1813 ; /* nothing to check before */
1815 else if (sRef_isParam (base))
1817 if (sRef_getParam (base) == argno - 1)
1821 DPRINTF (("Fix base: %s / %s",
1822 sRef_unparseFull (el),
1823 sRef_unparseFull (fref)));
1825 sb = sRef_fixBase (el, fref);
1827 if (tst != NULL && !(tst(sb)))
1830 (stateClause_preErrorCode (cl),
1831 message ("%s storage %qcorresponds to "
1832 "storage listed in %q clause of "
1833 "called function: %s",
1834 stateClause_preErrorString (cl, sb),
1835 sRef_unparseOpt (sb),
1836 stateClause_unparseKind (cl),
1837 exprNode_unparse (fexp)),
1838 exprNode_loc (fexp));
1843 DPRINTF (("Fixing: %s", sRef_unparseFull (sb)));
1844 modf (sb, exprNode_loc (fexp));
1845 DPRINTF (("==> %s", sRef_unparseFull (sb)));
1853 } end_sRefSet_elements ;
1855 } end_stateClauseList_preElements ;
1857 DPRINTF (("After: %s", sRef_unparseFull (fref)));
1861 ** should not modify arg
1865 transferChecks_passParam (exprNode fexp, uentry arg, bool isSpec,
1866 /*@dependent@*/ exprNode fcn, int argno, int totargs)
1868 sRef tref = uentry_getSref (arg);
1869 sRef fref = exprNode_getSref (fexp);
1871 bool isPartial = FALSE;
1872 bool isImpOut = FALSE;
1873 ctype ct = uentry_getType (arg);
1875 DPRINTF (("Check pass: %s -> %s",
1876 sRef_unparseFull (fref),
1877 sRef_unparseFull (tref)));
1881 atNumArgs = totargs;
1883 if (ctype_isElips (ct))
1888 DPRINTF (("Out arg: %s", bool_unparse (uentry_isOut (arg))));
1890 if (!ctype_isElips (ct) &&
1891 (ctype_isVoidPointer (ct) && uentry_isOut (arg) && sRef_isOnly (tref)))
1893 if (ctype_isRealAP (ct))
1895 if (sRef_aliasCheckSimplePred (sRef_isDead, fref))
1899 message ("Dead storage %qpassed as out parameter to %s: %s",
1900 sRef_unparseOpt (fref),
1901 exprNode_unparse (fcn),
1902 exprNode_unparse (fexp)),
1903 exprNode_loc (fexp)))
1905 if (sRef_isDead (fref))
1907 sRef_showStateInfo (fref);
1911 DPRINTF (("Not really dead!"));
1912 sRef_showStateInfo (fref);
1916 sRef_setAllocated (fref, exprNode_loc (fexp));
1918 else if (context_getFlag (FLG_STRICTUSERELEASED)
1919 && sRef_aliasCheckSimplePred (sRef_isPossiblyDead, fref))
1922 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1923 message ("Possibly dead storage %qpassed as out parameter: %s",
1924 sRef_unparseOpt (fref),
1925 exprNode_unparse (fexp)),
1926 exprNode_loc (fexp)))
1928 if (sRef_isPossiblyDead (fref))
1930 sRef_showStateInfo (fref);
1934 sRef_setAllocated (fref, exprNode_loc (fexp));
1936 else if (sRef_aliasCheckSimplePred (sRef_isStateUndefined, fref)
1937 || sRef_aliasCheckSimplePred (sRef_isUnuseable, fref))
1941 message ("Unallocated storage %qpassed as out parameter: %s",
1942 sRef_unparseOpt (fref),
1943 exprNode_unparse (fexp)),
1944 exprNode_loc (fexp));
1946 sRef_setAllocated (fref, exprNode_loc (fexp));
1954 (void) checkCompletelyDestroyed (fexp, fref, TRUE, FALSE,
1955 exprNode_loc (fexp), 0, DSC_PARAM, FALSE);
1957 /* make it defined now, so checkTransfer is okay */
1958 sRef_setDefined (fref, exprNode_loc (fexp));
1960 else if (uentry_isOut (arg))
1962 DPRINTF (("Here we are!"));
1964 if (ctype_isRealAP (ct)
1965 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1969 message ("Unallocated storage %qpassed as out parameter to %s: %s",
1970 sRef_unparseOpt (fref),
1971 exprNode_unparse (fcn),
1972 exprNode_unparse (fexp)),
1973 exprNode_loc (fexp));
1974 sRef_setAllocated (fref, exprNode_loc (fexp));
1976 else if (sRef_isDead (fref))
1980 message ("Dead storage %qpassed as out parameter to %s: %s",
1981 sRef_unparseOpt (fref),
1982 exprNode_unparse (fcn),
1983 exprNode_unparse (fexp)),
1984 exprNode_loc (fexp)))
1986 sRef_showStateInfo (fref);
1987 sRef_setAllocated (fref, exprNode_loc (fexp));
1990 else if (sRef_isPossiblyDead (fref))
1993 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1994 message ("Possibly dead storage %qpassed as out parameter to %s: %s",
1995 sRef_unparseOpt (fref),
1996 exprNode_unparse (fcn),
1997 exprNode_unparse (fexp)),
1998 exprNode_loc (fexp)))
2000 sRef_showStateInfo (fref);
2001 sRef_setAllocated (fref, exprNode_loc (fexp));
2011 else if (uentry_isPartial (arg))
2013 if (ctype_isRealAP (ct)
2014 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
2018 message ("Unallocated storage %qpassed as partial parameter: %s",
2019 sRef_unparseOpt (fref),
2020 exprNode_unparse (fexp)),
2021 exprNode_loc (fexp));
2022 sRef_setAllocated (fref, exprNode_loc (fexp));
2024 else if (sRef_isDead (fref))
2028 message ("Dead storage %qpassed as partial parameter to %s: %s",
2029 sRef_unparseOpt (fref),
2030 exprNode_unparse (fcn),
2031 exprNode_unparse (fexp)),
2032 exprNode_loc (fexp)))
2034 sRef_showStateInfo (fref);
2035 sRef_setAllocated (fref, exprNode_loc (fexp));
2038 else if (sRef_isPossiblyDead (fref))
2041 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
2042 message ("Possibly dead storage %qpassed as partial parameter to %s: %s",
2043 sRef_unparseOpt (fref),
2044 exprNode_unparse (fcn),
2045 exprNode_unparse (fexp)),
2046 exprNode_loc (fexp)))
2048 sRef_showStateInfo (fref);
2049 sRef_setAllocated (fref, exprNode_loc (fexp));
2059 else if (uentry_isStateSpecial (arg))
2061 uentry ue = exprNode_getUentry (fcn);
2063 if (ctype_isRealAP (ct)
2064 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
2068 message ("Unallocated storage %qpassed as special parameter: %s",
2069 sRef_unparseOpt (fref),
2070 exprNode_unparse (fexp)),
2071 exprNode_loc (fexp));
2072 sRef_setAllocated (fref, exprNode_loc (fexp));
2074 else if (sRef_isDead (fref))
2078 message ("Dead storage %qpassed as special parameter to %s: %s",
2079 sRef_unparseOpt (fref),
2080 exprNode_unparse (fcn),
2081 exprNode_unparse (fexp)),
2082 exprNode_loc (fexp)))
2084 sRef_showStateInfo (fref);
2085 sRef_setAllocated (fref, exprNode_loc (fexp));
2088 else if (sRef_isPossiblyDead (fref))
2091 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
2092 message ("Possibly dead storage %qpassed as special parameter to %s: %s",
2093 sRef_unparseOpt (fref),
2094 exprNode_unparse (fcn),
2095 exprNode_unparse (fexp)),
2096 exprNode_loc (fexp)))
2098 sRef_showStateInfo (fref);
2099 sRef_setAllocated (fref, exprNode_loc (fexp));
2107 if (uentry_hasStateClauseList (ue))
2109 checkPassstateClauseList (ue, fexp, fref, argno);
2114 else if (sRef_isStateDefined (tref))
2116 exprNode_checkUseParam (fexp);
2120 if (isSpec || (!context_getFlag (FLG_IMPOUTS)))
2122 exprNode_checkUseParam (fexp);
2126 if (!sRef_isMacroParamRef (fref)
2127 && (ctype_isRealAP (ct)))
2129 if (sRef_isAddress (fref))
2131 if (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref))
2136 ("Unallocated address %qpassed as implicit "
2137 "out parameter: %s",
2138 sRef_unparseOpt (fref),
2139 exprNode_unparse (fexp)),
2140 exprNode_loc (fexp));
2141 sRef_setAllocated (fref, exprNode_loc (fexp));
2145 /* yes, I really mean this! */
2146 tref = sRef_copy (tref);
2147 sRef_setAllocated (tref, exprNode_loc (fexp));
2154 exprNode_checkUseParam (fexp);
2159 if (sRef_isNew (fref))
2161 alkind tkind = sRef_getAliasKind (tref);
2163 if ((sRef_isFresh (fref) || sRef_isOnly (fref))
2164 && !alkind_isOnly (tkind)
2165 && !alkind_isKeep (tkind)
2166 && !alkind_isOwned (tkind)
2167 && !alkind_isError (tkind)
2168 && !uentry_isReturned (arg))
2173 message ("New fresh storage %q(type %s) passed as %s (not released): %s",
2174 sRef_unparseOpt (fref),
2175 ctype_unparse (sRef_getType (fref)),
2176 alkind_unparse (sRef_getAliasKind (tref)),
2177 exprNode_unparse (fexp)),
2178 exprNode_loc (fexp));
2180 DPRINTF (("Fresh: %s", sRef_unparseFull (fref)));
2184 if (sRef_isNewRef (fref) && !sRef_isKillRef (tref))
2186 alkind ak = sRef_getAliasKind (tref);
2188 if (!alkind_isError (ak))
2192 message ("New reference %q(type %s) passed as %s (not released): %s",
2193 sRef_unparseOpt (fref),
2194 ctype_unparse (sRef_getType (fref)),
2195 alkind_unparse (sRef_getAliasKind (tref)),
2196 exprNode_unparse (fexp)),
2197 exprNode_loc (fexp));
2203 (void) checkTransfer (fexp, exprNode_getSref (fexp),
2204 exprNode_undefined, tref,
2206 exprNode_loc (fexp), TT_FCNPASS);
2209 fref = exprNode_getSref (fexp);
2211 if (isOut && !sRef_isDead (fref) && !sRef_isPossiblyDead (fref))
2215 if (ctype_isRealAP (sRef_getType (fref)))
2217 base = sRef_makePointer (fref);
2226 exprNode_checkMSet (fexp, base);
2230 exprNode_checkSet (fexp, base);
2233 if (sRef_isValid (base))
2237 sRef_clearDerived (base);
2238 sRef_setDefined (base, exprNode_loc (fexp));
2239 usymtab_clearAlias (base);
2240 sRef_setNullUnknown (base, exprNode_loc (fexp));
2246 if (sRef_isValid (fref))
2248 sRef_setPartial (fref, exprNode_loc (fexp));
2252 atFunction = exprNode_undefined;
2256 /* need to fixup here: derived refs could be bogus */
2257 /* (better to change sRef to not add derivs for "protected" ref) */
2259 uentry_fixupSref (arg);
2263 DPRINTF (("Check pass: ==> %s",
2264 sRef_unparseFull (fref)));
2268 transferChecks_globalReturn (uentry glob)
2270 sRef_protectDerivs ();
2271 checkGlobTrans (glob, TT_GLOBRETURN);
2272 sRef_clearProtectDerivs ();
2275 void transferChecks_paramReturn (uentry actual)
2277 checkLeaveTrans (actual, TT_PARAMRETURN);
2280 void transferChecks_loseReference (uentry actual)
2282 checkLeaveTrans (actual, TT_LEAVETRANS);
2286 checkLeaveTrans (uentry actual, transferKind transferType)
2288 sRef aref = uentry_getSref (actual);
2289 sRef origref = uentry_getOrigSref (actual);
2291 if (transferType == TT_PARAMRETURN
2292 && (sRef_isKeep (origref) || sRef_isOnly (origref)
2293 || sRef_isOwned (origref)))
2295 /* caller cannot use, nothing to check */
2299 if (sRef_isNSLocalVar (origref))
2305 DPRINTF (("Leave trans: %s", uentry_unparseFull (actual)));
2307 (void) checkCompletelyDefined (exprNode_undefined, aref, aref,
2308 exprNode_undefined, origref,
2310 g_currentloc, transferType,
2317 checkGlobTrans (uentry glob, transferKind type)
2319 sRef eref = uentry_getOrigSref (glob);
2321 DPRINTF (("Completely defined: %s", uentry_unparseFull (glob)));
2323 (void) checkCompletelyDefined (exprNode_undefined, uentry_getSref (glob),
2324 uentry_getSref (glob),
2325 exprNode_undefined, eref,
2327 g_currentloc, type, 0, TRUE);
2331 ** For lhs of assignment, alias kind is set from basic type.
2336 fixAssignLhs (sRef s)
2338 sRef_resetStateComplete (s);
2341 static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srhs,
2345 ctype st = ctype_realType (sRef_getType (srhs));
2347 if (ctype_isSU (st) && ctype_isRealSU (sRef_getType (slhs))
2348 && ctype_match (sRef_getType (slhs), st))
2350 if (tt == TT_DOASSIGN && sRef_isStateDefined (srhs))
2352 sRef_setDefinedComplete (slhs, loc);
2355 if (sRef_isDependent (slhs)
2356 || sRef_isObserver (slhs)
2357 || sRef_isExposed (slhs))
2363 if (sRef_isLocalVar (slhs)
2364 && sRef_isFileOrGlobalScope (sRef_getRootBase (srhs)))
2366 sRef_setDependent (slhs, exprNode_loc (lhs));
2370 if (ctype_isUnion (st))
2372 sRef_setDefState (slhs, sRef_getDefState (srhs),
2373 exprNode_loc (lhs));
2375 sRefSet_realElements (sRef_derivedFields (srhs), sr)
2377 if (sRef_isField (sr))
2379 cstring fieldname = sRef_getField (sr);
2380 sRef lfld = sRef_makeField (slhs, fieldname);
2382 (void) checkTransfer (rhs, sr, lhs, lfld,
2384 exprNode_loc (lhs), tt);
2386 } end_sRefSet_realElements ;
2390 uentryList fields = ctype_getFields (st);
2392 uentryList_elements (fields, field)
2394 sRef rfld = sRef_makeField (srhs, uentry_rawName (field));
2395 sRef lfld = sRef_makeField (slhs, uentry_rawName (field));
2396 (void) checkTransfer (rhs, rfld, lhs, lfld,
2398 exprNode_loc (lhs), tt);
2399 } end_uentryList_elements ;
2402 if (sRef_isOnly (srhs))
2404 sRef_setKeptComplete (srhs, loc);
2412 transferChecks_initialization (exprNode lhs, exprNode rhs)
2414 sRef slhs = exprNode_getSref (lhs);
2416 if (sRef_isFileOrGlobalScope (slhs) || (!sRef_isCvar (slhs)))
2418 (void) checkTransfer (rhs, exprNode_getSref (rhs),
2421 exprNode_loc (rhs), TT_GLOBINIT);
2425 transferChecks_assign (lhs, rhs);
2430 transferChecks_assign (exprNode lhs, exprNode rhs)
2432 sRef slhs = exprNode_getSref (lhs);
2433 sRef srhs = exprNode_getSref (rhs);
2434 sRef base = sRef_getBaseSafe (slhs);
2437 DPRINTF (("Check assign: %s = %s", exprNode_unparse (lhs),
2438 exprNode_unparse (rhs)));
2439 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2440 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2442 if (ctype_isRealSU (sRef_getType (srhs)))
2444 checkStructTransfer (lhs, slhs, rhs, srhs, exprNode_loc (lhs), TT_FIELDASSIGN);
2448 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2449 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2450 (void) checkTransfer (rhs, srhs, lhs, slhs,
2452 exprNode_loc (lhs), TT_DOASSIGN);
2453 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2454 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2457 if (sRef_isConst (srhs) && sRef_isLocalState (srhs))
2459 /* constants can match anything (e.g., NULL) */
2460 sRef_setAliasKind (slhs, AK_ERROR, fileloc_undefined);
2463 if (sRef_isValid (base) && sRef_isStateDefined (base))
2465 sRef_setPdefined (base, g_currentloc);
2468 if (sRef_isPartial (srhs))
2470 sRef_setPartial (slhs, exprNode_loc (rhs));
2473 ns = sRef_getNullState (srhs);
2475 if (nstate_possiblyNull (ns))
2477 if (usymtab_isGuarded (srhs))
2483 sRef_setNullStateInnerComplete (slhs, ns, exprNode_loc (rhs));
2485 if (sRef_isExposed (srhs) || sRef_isObserver (srhs))
2487 sRef_setExKind (slhs, sRef_getExKind (srhs), exprNode_loc (rhs));
2490 DPRINTF (("Done transfer: %s", sRef_unparseFull (slhs)));
2494 checkTransferNullAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2495 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2496 fileloc loc, transferKind transferType)
2498 alkind tkind = sRef_getAliasKind (tref);
2499 ctype ttyp = ctype_realType (sRef_getType (tref));
2501 if (ctype_isUnknown (ttyp))
2503 ttyp = exprNode_getType (texp);
2505 if (ctype_isUnknown (ttyp))
2507 ttyp = exprNode_getType (fexp);
2509 if (ctype_isUnknown (ttyp))
2511 ttyp = sRef_getType (fref);
2516 if (ctype_isFunction (ttyp) && (transferType == TT_FCNRETURN))
2518 ttyp = ctype_getReturnType (ttyp);
2522 ** check for null (don't need to check aliases??)
2525 if (sRef_possiblyNull (fref)
2526 && !usymtab_isGuarded (fref)
2527 && ctype_isRealAP (ttyp))
2529 if (!alkind_isLocal (tkind) && !alkind_isFresh (tkind)
2530 && !sRef_perhapsNull (tref)
2531 && !(transferType == TT_DOASSIGN))
2533 if (transferType == TT_GLOBINIT)
2535 if (sRef_isNotNull (tref))
2538 (FLG_SYNTAX, /*@i432 kuldge flag... */
2539 message ("%s %q initialized to %s value: %q",
2540 sRef_getScopeName (tref),
2541 sRef_unparse (tref),
2542 sRef_nullMessage (fref),
2543 generateText (fexp, texp, tref, transferType)),
2546 sRef_showNullInfo (fref);
2547 sRef_setNullError (tref);
2554 message ("%s %q initialized to %s value: %q",
2555 sRef_getScopeName (tref),
2556 sRef_unparse (tref),
2557 sRef_nullMessage (fref),
2558 generateText (fexp, texp, tref, transferType)),
2561 sRef_showNullInfo (fref);
2562 sRef_setNullError (tref);
2569 ((transferType == TT_FCNPASS) ? FLG_NULLPASS : FLG_NULLRET,
2570 message ("%q storage %q%s: %q",
2571 cstring_capitalize (sRef_nullMessage (fref)),
2572 sRef_unparseOpt (fref),
2573 transferNullMessage (transferType),
2574 generateText (fexp, texp, tref, transferType)),
2577 sRef_showNullInfo (fref);
2578 sRef_setNullError (fref);
2591 checkTransferAssignAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2592 /*@exposed@*/ sRef tref, exprNode texp, bool tfix,
2593 fileloc loc, transferKind transferType)
2595 alkind tkind = sRef_getAliasKind (tref);
2598 ** Assignment to same --- no errors, or state changes.
2599 ** This can happen when returned params are used.
2602 if (sRef_sameName (fref, tref))
2604 sRef_copyState (tref, fref);
2608 if ((alkind_isOnly (tkind) || alkind_isFresh (tkind)
2609 || alkind_isNewRef (tkind) || alkind_isOwned (tkind))
2610 && !(sRef_isDead (tref)
2611 || sRef_isStateUndefined (tref)
2612 || sRef_isUnuseable (tref)
2613 || sRef_isPartial (tref)
2614 || sRef_definitelyNull (tref)
2615 || sRef_isStackAllocated (tref)
2616 || sRef_isAllocIndexRef (tref))
2617 && !(sRef_same (fref, tref)) /* okay to assign to self (returned params) */
2618 && !(usymtab_isDefinitelyNull (tref)))
2620 if (transferChecks_canLoseReference (tref, loc))
2626 flagcode flg = sRef_isFresh (tref) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY;
2628 if (sRef_hasLastReference (tref))
2632 message ("Last reference %q to %s storage %q(type %s) not released "
2633 "before assignment: %q",
2634 sRef_unparse (tref),
2635 alkind_unparse (tkind),
2636 sRef_unparseOpt (sRef_getAliasInfoRef (tref)),
2637 ctype_unparse (sRef_getType (tref)),
2638 generateText (fexp, texp, tref, transferType)),
2641 sRef_showRefLost (tref);
2646 if (context_inGlobalScope ())
2648 /* no errors for static initializations */
2653 ** don't report this error for a[i], since it could
2654 ** be a new element.
2657 if (alkind_isNewRef (tkind))
2662 ("%q %q(type %s) not released before assignment: %q",
2664 (alkind_isKillRef (sRef_getOrigAliasKind (tref))
2665 ? "Kill reference parameter" : "New reference"),
2666 sRef_unparseOpt (tref),
2667 ctype_unparse (sRef_getType (tref)),
2668 generateText (fexp, texp, tref, transferType)),
2671 sRef_showAliasInfo (tref);
2672 sRef_setAliasKind (tref, AK_ERROR, loc);
2676 (!(sRef_isUnknownArrayFetch (tref)
2677 && !context_getFlag (FLG_STRICTDESTROY))
2678 && !sRef_isUnionField (tref)
2679 && !sRef_isRelDef (tref)
2683 ("%s storage %q(type %s) not released before assignment: %q",
2684 alkind_capName (tkind),
2685 sRef_unparseOpt (tref),
2686 ctype_unparse (sRef_getType (tref)),
2687 generateText (fexp, texp, tref, transferType)),
2690 sRef_showAliasInfo (tref);
2701 fixAssignLhs (tref);
2703 if (sRef_isRefCounted (tref)) /* tkind might not be correct now */
2705 if (sRef_isNewRef (fref))
2707 sRef_setAliasKind (tref, AK_NEWREF, loc);
2709 else if (sRef_isConst (fref))
2711 /* for now, constants are not ref counted */
2712 sRef_setAliasKind (tref, AK_ERROR, loc);
2719 if (!sRef_isNSLocalVar (tref)
2720 && sRef_isRefCounted (fref)
2721 && sRef_isStateDefined (fref))
2725 message ("New reference %qto reference counted storage: %q",
2726 sRef_unparseOpt (tref),
2727 generateText (fexp, texp, tref, transferType)),
2733 ** Not for structures and unions, since assignments copy.
2736 if (sRef_isStack (fref)
2737 && !ctype_isSU (ctype_realType (sRef_getType (fref))))
2739 sRef_setAliasKindComplete (tref, AK_STACK, loc);
2742 if (sRef_isNSLocalVar (tref)
2743 && !sRef_isOwned (tref) /*< should only apply to static >*/
2744 && ctype_isMutable (sRef_getType (tref)))
2746 if (sRef_isOnly (fref) && sRef_isNew (fref))
2750 sRef_setFresh (tref, loc);
2757 ** requires sRef_isOnly (fref)
2761 checkOnlyTransferAux (sRef fref, exprNode fexp, bool ffix,
2762 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2763 fileloc loc, transferKind transferType)
2765 alkind tkind = sRef_getAliasKind (tref);
2767 if (sRef_isExposed (tref) || sRef_isObserver (tref))
2769 if (transferType == TT_FCNRETURN && sRef_isNew (fref)
2770 && !alkind_isError (tkind))
2774 message ("Only storage %q%q (will not be released): %q",
2775 sRef_unparseOpt (fref),
2776 transferErrorMessage (transferType, tkind),
2777 generateText (fexp, texp, tref, transferType)),
2780 sRef_showAliasInfo (fref);
2784 /* no errors for exposed transfers (is this good enough?) */
2786 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind) || alkind_isOwned (tkind))
2790 else if ((transferType == TT_FCNPASS)
2791 && (alkind_isUnknown (tkind)
2792 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2794 if (sRef_isFresh (fref)
2795 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2797 if (!ffix) sRef_setAliasKind (fref, AK_UNKNOWN, loc);
2800 else if (alkind_isLocal (tkind)
2801 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2803 if ((transferType == TT_DOASSIGN)
2804 && sRef_isNew (fref)
2805 && sRef_isOnly (fref))
2809 if (alkind_isUnknown (tkind)
2810 && sRef_isFileOrGlobalScope (sRef_getRootBase (tref)))
2813 (FLG_ONLYUNQGLOBALTRANS,
2814 message ("Only storage %q%q: %q",
2815 sRef_unparseOpt (fref),
2816 transferErrorMessage (transferType, tkind),
2817 generateText (fexp, texp, tref, transferType)),
2820 sRef_showAliasInfo (fref);
2821 sRef_setAliasKind (tref, AK_ERROR, loc);
2826 if (!error && !ffix)
2828 sRef_setFresh (tref, loc);
2833 if (alkind_isLocal (tkind))
2835 if (sRef_sameName (tref, fref))
2837 ; /* don't set this --- corresponds to return transfer */
2842 ** Don't set local to dependent. Error will
2843 ** be detected through aliasing. Except for
2847 if (!tfix && sRef_isThroughArrayFetch (fref)
2848 && context_getFlag (FLG_DEPARRAYS))
2850 sRef_setDependent (tref, loc);
2858 message ("Only storage %q%q: %q",
2859 sRef_unparseOpt (fref),
2860 transferErrorMessage (transferType, tkind),
2861 generateText (fexp, texp, tref, transferType)),
2864 sRef_showAliasInfo (fref);
2871 if (alkind_isError (tkind)
2872 || (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT)))
2874 flagcode_recordSuppressed (FLG_ONLYTRANS);
2878 if ((alkind_isKept (tkind) || alkind_isStack (tkind)
2879 || alkind_isDependent (tkind))
2880 && sRef_isNSLocalVar (tref))
2888 message ("Only storage %q%q: %q",
2889 sRef_unparseOpt (fref),
2890 transferErrorMessage (transferType, tkind),
2891 generateText (fexp, texp, tref, transferType)),
2894 sRef_showAliasInfo (fref);
2896 if (transferType == TT_DOASSIGN)
2899 ** alias kind unknown to suppress future messages
2902 if (!ffix && sRef_isNSLocalVar (sRef_getRootBase (fref)))
2904 sRef_clearAliasKind (fref);
2914 ** ??? same as checkOnly ?
2918 checkOwnedTransferAux (sRef fref, exprNode fexp, bool ffix,
2919 sRef tref, exprNode texp, bool tfix,
2920 fileloc loc, transferKind transferType)
2922 alkind tkind = sRef_getAliasKind (tref);
2924 if (sRef_isExposed (tref) || sRef_isObserver (tref))
2926 if (transferType == TT_FCNRETURN && sRef_isNew (fref))
2930 message ("Owned storage %q%q (will not be released): %q",
2931 sRef_unparseOpt (fref),
2932 transferErrorMessage (transferType, tkind),
2933 generateText (fexp, texp, tref, transferType)),
2936 sRef_showAliasInfo (fref);
2940 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind)
2941 || alkind_isDependent (tkind)
2942 || alkind_isOwned (tkind))
2946 else if (alkind_isLocal (tkind)
2947 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2949 if ((transferType == TT_DOASSIGN)
2950 && sRef_isNew (fref) && sRef_isOnly (fref))
2954 sRef_setFresh (tref, loc);
2961 else if ((transferType == TT_FCNPASS)
2962 && (alkind_isUnknown (tkind)
2963 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2965 if (sRef_isFresh (fref)
2966 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2968 if (!ffix) { sRef_clearAliasKind (fref); }
2973 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2975 flagcode_recordSuppressed (FLG_OWNEDTRANS);
2979 if (alkind_isKept (tkind) && sRef_isNSLocalVar (tref))
2987 message ("Owned storage %q%q: %q",
2988 sRef_unparseOpt (fref),
2989 transferErrorMessage (transferType, tkind),
2990 generateText (fexp, texp, tref, transferType)),
2995 if (transferType == TT_DOASSIGN)
2998 ** alias kind unknown to suppress future messages
3001 if (!ffix) { sRef_clearAliasKind (fref); }
3007 checkFreshTransferAux (sRef fref, exprNode fexp, bool ffix,
3008 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
3009 fileloc loc, transferKind transferType)
3011 alkind tkind = sRef_getAliasKind (tref);
3014 ** error to return fresh as non-only
3017 if (transferType == TT_FCNRETURN
3018 && !(alkind_isOnly (tkind) || alkind_isNewRef (tkind)))
3020 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
3022 flagcode_recordSuppressed (FLG_NEWREFTRANS);
3026 if (alkind_isError (tkind))
3030 sRef_killComplete (fref, loc);
3033 else if (alkind_isRefCounted (tkind))
3038 ("New reference returned without newref qualifier: %q",
3039 generateText (fexp, texp, tref, transferType)),
3042 sRef_showAliasInfo (fref);
3043 sRef_killComplete (fref, loc);
3050 message ("Fresh storage %q (should be only): %q",
3051 transferErrorMessage (transferType, tkind),
3052 generateText (fexp, texp, tref, transferType)),
3055 sRef_showAliasInfo (fref);
3056 sRef_killComplete (fref, loc);
3063 ** Okay to assign fresh to only, shared or unqualified.
3065 ** should generate other errors?
3068 if (alkind_isOnly (tkind))
3070 if (transferType == TT_DOASSIGN && !sRef_isFileOrGlobalScope (tref))
3074 if (!sRef_isNSLocalVar (tref))
3076 sRef_setKeptComplete (fref, loc);
3082 if (sRef_isConst (fref))
3090 sRef_killComplete (fref, loc);
3095 else if (alkind_isOwned (tkind))
3099 sRef_setDependentComplete (fref, loc);
3102 else if (alkind_isRefCounted (tkind)
3103 && (transferType == TT_FCNRETURN) && sRef_isFresh (fref))
3107 sRef_killComplete (fref, loc);
3110 else if (alkind_isKeep (tkind))
3114 if (!sRef_isNSLocalVar (tref))
3116 sRef_setKeptComplete (fref, loc);
3120 else if (alkind_isShared (tkind))
3122 if (!ffix) { sRef_setShared (fref, loc); }
3124 else if (alkind_isLocal (tkind) || alkind_isUnknown (tkind))
3126 if (transferType == TT_DOASSIGN || transferType == TT_FCNRETURN)
3129 ** local shares fresh. Make it owned/dependent.
3134 sRef_setOwned (tref, loc);
3139 sRef_setDependentComplete (fref, loc);
3142 /* NO! sRef_clearAliasKind (fref); */
3146 if (context_getFlag (FLG_PASSUNKNOWN))
3148 sRef_clearAliasKind (fref);
3159 checkTransferExposure (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
3160 sRef tref, exprNode texp, bool tfix,
3162 transferKind transferType)
3164 alkind fkind = sRef_getAliasKind (fref);
3165 alkind tkind = sRef_getAliasKind (tref);
3166 exkind tekind = sRef_getExKind (tref);
3168 if (sRef_isObserver (fref) && ctype_isMutable (sRef_getType (fref)))
3171 ** observer -> exposed or observer
3175 ** observer -> temp is okay [NO! really? only in function calls]
3178 if (sRef_isExposed (tref) || sRef_isObserver (tref)
3179 || alkind_isLocal (tkind))
3183 if ((transferType == TT_DOASSIGN) && alkind_isLocal (tkind))
3187 sRef_setAliasKindComplete (tref, fkind, loc);
3193 if (transferType == TT_FCNRETURN
3194 || transferType == TT_DOASSIGN
3195 || transferType == TT_FIELDASSIGN
3196 || transferType == TT_GLOBINIT)
3198 bool hasError = FALSE;
3200 if (exprNode_isStringLiteral (fexp)
3201 && transferType == TT_GLOBINIT)
3203 hasError = optgenerror
3205 message ("Read-only string literal storage %q%q: %q",
3206 sRef_unparseOpt (fref),
3207 transferErrorExpMessage (transferType, tekind),
3208 generateText (fexp, texp, tref, transferType)),
3211 sRef_setAliasKind (fref, AK_ERROR, fileloc_undefined);
3215 if ((transferType == TT_DOASSIGN
3216 || transferType == TT_FIELDASSIGN)
3217 && (sRef_isNSLocalVar (tref)
3218 || (exprNode_isStringLiteral (fexp)
3219 && ctype_isRealArray (exprNode_getType (texp)))))
3221 ; /* No error for local assignment or assignment
3222 to static array (copies string). */
3226 if (exprNode_isStringLiteral (fexp))
3228 hasError = optgenerror
3231 ("Read-only string literal storage %q%q: %q",
3232 sRef_unparseOpt (fref),
3233 transferErrorExpMessage (transferType, tekind),
3234 generateText (fexp, texp, tref, transferType)),
3241 hasError = optgenerror
3244 ("Observer storage %q%q: %q",
3245 sRef_unparseOpt (fref),
3246 transferErrorExpMessage (transferType, tekind),
3247 generateText (fexp, texp, tref, transferType)),
3255 if (transferType != TT_GLOBINIT)
3257 sRef_showExpInfo (fref);
3258 sRef_setAliasKind (tref, AK_ERROR, loc);
3263 if (transferType == TT_DOASSIGN && !tfix)
3265 DPRINTF (("Setting unknown!"));
3266 /* sRef_setAliasKind (tref, AK_ERROR, loc); */
3270 else /* TT_FCNPASS */
3272 llassert (transferType == TT_FCNPASS);
3274 if (alkind_isTemp (tkind)
3275 || alkind_isDependent (tkind)
3276 || alkind_isRefCounted (tkind))
3282 if (!alkind_isError (tkind))
3286 message ("Observer storage %q%q: %q",
3287 sRef_unparseOpt (fref),
3288 transferErrorMessage (transferType, tkind),
3289 generateText (fexp, texp, tref, transferType)),
3292 sRef_showExpInfo (fref);
3293 sRef_clearAliasState (fref, loc);
3300 else if (sRef_isExposed (fref) && ctype_isMutable (sRef_getType (fref)))
3302 if (transferType == TT_FCNRETURN)
3304 if (!(sRef_isExposed (tref) || sRef_isObserver (tref)
3305 || sRef_isParam (fref)))
3309 message ("Exposed storage %q%q: %q",
3310 sRef_unparseOpt (fref),
3311 transferErrorExpMessage (transferType, tekind),
3312 generateText (fexp, texp, tref, transferType)),
3315 sRef_showExpInfo (fref);
3319 else if (transferType == TT_FCNPASS)
3321 if (!(sRef_isExposed (tref)
3322 || sRef_isObserver (tref)
3323 || (alkind_isUnknown (tkind)
3324 || alkind_isDependent (tkind)
3325 || alkind_isTemp (tkind)
3326 || alkind_isKillRef (tkind)
3327 || alkind_isRefCounted (tkind))))
3329 if (alkind_isUnique (tkind) || alkind_isError (tkind))
3336 message ("Exposed storage %q%q: %q",
3337 sRef_unparseOpt (fref),
3338 transferErrorMessage (transferType, tkind),
3339 generateText (fexp, texp, tref, transferType)),
3342 sRef_showExpInfo (fref);
3343 sRef_clearAliasState (fref, loc);
3353 else if (transferType == TT_DOASSIGN
3354 /* evans 2001-10-05: added TT_FIELDASSIGN: */
3355 || transferType == TT_FIELDASSIGN)
3357 if (!(sRef_isExposed (tref)
3358 || !sRef_isCvar (tref)
3359 || (alkind_isUnknown (tkind)
3360 || alkind_isDependent (tkind)
3361 || alkind_isRefCounted (tkind)
3362 || alkind_isNewRef (tkind)
3363 || alkind_isFresh (tkind)
3364 || alkind_isLocal (tkind))))
3368 message ("Exposed storage %q%q: %q",
3369 sRef_unparseOpt (fref),
3370 transferErrorExpMessage (transferType, tekind),
3371 generateText (fexp, texp, tref, transferType)),
3374 sRef_showExpInfo (fref);
3377 if (!tfix) { sRef_setExposed (tref, loc); }
3381 llassert (transferType == TT_GLOBPASS
3382 || transferType == TT_GLOBRETURN
3383 || transferType == TT_PARAMRETURN
3384 || transferType == TT_LEAVETRANS
3385 || transferType == TT_GLOBINIT);
3395 ** returns TRUE if there is no error reported
3397 ** if fixt, don't change tref (except if error reported.)
3398 ** if fixf, don't change fref (except if error reported.)
3402 checkTransferAux (exprNode fexp, /*@exposed@*/ sRef fref, bool ffix,
3403 exprNode texp, /*@exposed@*/ sRef tref, bool tfix,
3404 fileloc loc, transferKind transferType)
3408 bool isassign = (transferType == TT_DOASSIGN);
3409 bool isfieldassign = (transferType == TT_FIELDASSIGN);
3410 bool iseitherassign = isassign || (transferType == TT_FIELDASSIGN);
3411 bool isfcnpass = (transferType == TT_FCNPASS);
3412 bool isfcnreturn = (transferType == TT_FCNRETURN);
3419 checkTransferNullAux (fref, fexp, ffix, tref, texp, tfix,
3426 checkTransferAssignAux (fref, fexp, ffix, tref, texp, tfix,
3431 ** Check for definition
3435 ** errors passing out params already detected in checkAnyCall
3443 || (!sRef_isNSLocalVar (tref)
3444 && (sRef_isAnyDefined (tref) || !sRef_stateKnown (tref))))
3448 if (!ynm_toBoolRelaxed
3449 (checkCompletelyDefined (fexp, fref, fref,
3452 loc, transferType, 0, TRUE)))
3460 if (defok && iseitherassign)
3462 sRef_setDefState (tref, sRef_getDefState (fref), loc);
3471 checkTransferExposure (fref, fexp, ffix, tref, texp, tfix,
3474 fkind = sRef_getAliasKind (fref);
3475 tkind = sRef_getAliasKind (tref);
3481 if (alkind_isOnly (fkind))
3484 checkOnlyTransferAux (fref, fexp, ffix,
3488 else if (alkind_isFresh (fkind))
3491 checkFreshTransferAux (fref, fexp, ffix,
3495 else if (alkind_isOwned (fkind))
3498 checkOwnedTransferAux (fref, fexp, ffix,
3502 else if (alkind_isDependent (fkind))
3506 (sRef_isExposed (tref) || sRef_isObserver (tref)))
3510 else if ((alkind_isOnly (tkind) || alkind_isKeep (tkind)
3511 || alkind_isOwned (tkind))
3512 || (!isfcnpass && alkind_isTemp (tkind)))
3516 if (sRef_isLocalVar (fref))
3518 sRef depRef = dependentReference (fref);
3520 if (sRef_isValid (depRef) && sRef_isLocalVar (depRef))
3523 sRef_kill (depRef, loc);
3524 sRef_kill (fref, loc);
3534 if (canLoseLocalReference (fref, loc))
3542 (FLG_DEPENDENTTRANS,
3543 message ("%s storage %q%q: %q",
3544 alkind_capName (fkind),
3545 sRef_unparseOpt (fref),
3546 transferErrorMessage (transferType, tkind),
3547 generateText (fexp, texp, tref, transferType)),
3550 DPRINTF (("Here: %s / %s",
3551 sRef_unparseFull (fref),
3552 sRef_unparseFull (tref)));
3554 sRef_showAliasInfo (fref);
3560 if (isassign && (alkind_isFresh (tkind) || alkind_isLocal (tkind)))
3564 sRef_setDependent (tref, loc);
3569 else if (alkind_isShared (fkind))
3576 if (alkind_isOnly (tkind)
3578 && (!(sRef_isObserver (tref) || sRef_isExposed (tref))
3579 && alkind_isTemp (tkind))))
3583 message ("%s storage %q%q: %q",
3584 alkind_capName (fkind),
3585 sRef_unparseOpt (fref),
3586 transferErrorMessage (transferType, tkind),
3587 generateText (fexp, texp, tref, transferType)),
3590 sRef_showAliasInfo (fref);
3595 if (alkind_isFresh (tkind) || alkind_isLocal (tkind))
3597 sRef_setShared (tref, loc);
3601 else if (alkind_isKeep (fkind))
3605 if (alkind_isKeep (tkind)
3606 || alkind_isLocal (tkind)
3607 || (isfcnreturn && sRef_isExposed (tref))
3609 && (alkind_isOnly (tkind) || alkind_isOwned (tkind))))
3611 sRef_setKept (fref, loc);
3614 && (alkind_isTemp (tkind) || alkind_isOwned (tkind)))
3620 if (!alkind_isError (tkind))
3624 message ("%s storage %q: %q",
3625 alkind_capName (fkind),
3626 transferErrorMessage (transferType, tkind),
3627 generateText (fexp, texp, tref, transferType)),
3630 sRef_showAliasInfo (fref);
3635 else if (alkind_isTemp (fkind) || alkind_isKept (fkind))
3641 if (alkind_isOnly (tkind)
3642 || alkind_isShared (tkind)
3643 || (alkind_isTemp (fkind)
3644 && !isfcnreturn && alkind_isDependent (tkind))
3645 || alkind_isOwned (tkind)
3646 || alkind_isKeep (tkind))
3648 if (!exprNode_isNullValue (fexp)
3649 && (ctype_isMutable (exprNode_getType (fexp))
3650 || (ctype_isArray (exprNode_getType (fexp))
3651 && sRef_isParam (fref)))
3652 && (!iseitherassign || sRef_isReference (tref)))
3654 if (sRef_isThroughArrayFetch (fref))
3657 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3658 FLG_STRICTUSERELEASED,
3659 message ("%s storage %q%q: %q",
3660 alkind_capName (fkind),
3661 sRef_unparseOpt (fref),
3662 transferErrorMessage (transferType, tkind),
3663 generateText (fexp, texp, tref, transferType)),
3666 sRef_showAliasInfo (fref);
3672 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3673 message ("%s storage %q%q: %q",
3674 alkind_capName (fkind),
3675 sRef_unparseOpt (fref),
3676 transferErrorMessage (transferType, tkind),
3677 generateText (fexp, texp, tref, transferType)),
3680 sRef_showAliasInfo (fref);
3686 else if (alkind_isRefCounted (fkind) || alkind_isKillRef (fkind))
3688 if (alkind_isNewRef (tkind))
3691 ** check that the refs field has been modified
3694 if (!sRef_isConst (fref))
3698 message ("Reference counted storage returned without modifying "
3699 "reference count: %s",
3700 exprNode_unparse (fexp)),
3704 else if (iseitherassign)
3706 if (alkind_isRefCounted (fkind))
3708 if (!sRef_isLocalVar (tref))
3713 ("Assignment to non-local from reference counted storage: %s",
3714 exprNode_unparse (fexp)),
3716 ("Reference counted storage should call a function returning "
3717 "a newref instead of direct assignments."),
3728 if (alkind_isRefCounted (tkind) || alkind_isTemp (tkind))
3730 /* okay --- no change in state */
3732 else if (alkind_isKillRef (tkind))
3734 if (!ffix && !tfix && !(transferType == TT_FCNRETURN))
3736 sRef_killComplete (fref, loc);
3741 if (!alkind_isError (tkind))
3745 message ("Reference counted storage %q: %q",
3746 transferErrorMessage (transferType, tkind),
3747 generateText (fexp, texp, tref, transferType)),
3760 if (alkind_isOnly (tkind) || alkind_isKeep (tkind))
3762 if (sRef_isAddress (fref))
3765 (FLG_IMMEDIATETRANS,
3766 message ("Immediate address %q %q: %q",
3767 sRef_unparse (fref),
3768 transferErrorMessage (transferType, tkind),
3769 generateText (fexp, texp, tref, transferType)),
3772 sRef_setAliasKind (fref, AK_ERROR, loc);
3776 if ((alkind_isUnknown (fkind) || alkind_isStatic (fkind))
3777 && !sRef_isDefinitelyNull (fref)
3779 && (!exprNode_isNullValue (fexp)))
3781 flagcode errkind = alkind_isStatic (fkind)
3782 ? FLG_STATICTRANS : FLG_UNKNOWNTRANS;
3784 if (transferType == TT_GLOBINIT)
3786 if (errkind == FLG_STATICTRANS)
3788 errkind = FLG_STATICINITTRANS;
3792 errkind = FLG_UNKNOWNINITTRANS;
3798 message ("%s storage %s %q: %q",
3799 alkind_capName (fkind),
3800 exprNode_unparse (fexp),
3801 transferErrorMessage (transferType, tkind),
3802 generateText (fexp, texp, tref, transferType)),
3805 sRef_showAliasInfo (fref);
3810 /* don't kill shared to suppress future messages */
3811 if (!alkind_isShared (fkind))
3817 /*< yuk! should do this in aliasaux >*/
3819 if (!sRef_isNSLocalVar (tref) && !sRef_sameName (fref, tref))
3823 sRef_setKeptComplete (fref, loc);
3827 sRef_setKept (fref, loc);
3838 if (alkind_isKeep (tkind))
3840 sRef_setKeptComplete (fref, loc);
3844 sRef_killComplete (fref, loc);
3849 if (alkind_isKeep (tkind))
3851 sRef_setKept (fref, loc);
3855 sRef_kill (fref, loc);
3862 else if (alkind_isOwned (tkind))
3864 /* don't kill shared to suppress future messages */
3865 if (!alkind_isShared (fkind))
3868 || !sRef_sameName (fref, tref)) /* result of return parameter */
3874 sRef_setDependentComplete (fref, loc);
3878 sRef_setDependent (fref, loc);
3884 else if (alkind_isShared (tkind))
3886 if (alkind_isFresh (fkind) || alkind_isLocal (fkind))
3890 sRef_setShared (fref, loc);
3894 else if (alkind_isUnknown (tkind) && context_getFlag (FLG_MEMIMPLICIT))
3896 if (alkind_isDependent (fkind))
3898 if (!exprNode_isNullValue (fexp)
3899 && ctype_isMutable (exprNode_getType (fexp))
3900 && (!iseitherassign || sRef_isReference (tref)))
3902 if (transferChecks_canLoseReference (fref, loc))
3909 (FLG_DEPENDENTTRANS,
3910 message ("%s storage %q%q: %q",
3911 alkind_capName (fkind),
3912 sRef_unparseOpt (fref),
3913 transferErrorMessage (transferType, tkind),
3914 generateText (fexp, texp, tref, transferType)),
3917 DPRINTF (("Here: %s / %s", sRef_unparseFull (fref),
3918 sRef_unparseFull (tref)));
3919 sRef_showAliasInfo (fref);
3925 else if (alkind_isNewRef (tkind))
3929 sRef_killComplete (fref, loc);
3932 else if (alkind_isKillRef (tkind))
3934 if (transferType == TT_FCNRETURN)
3936 if (sRef_isNewRef (fref))
3940 message ("New reference returned as temp reference: %q",
3941 generateText (fexp, texp, tref, transferType)),
3944 sRef_showAliasInfo (fref);
3950 if (sRef_isNewRef (fref))
3952 sRef_killComplete (fref, loc);
3956 if (sRef_isRefCounted (fref)
3957 && sRef_isCvar (fref)
3958 && !sRef_isLocalVar (fref))
3963 ("External reference counted storage released: %q",
3964 generateText (fexp, texp, tref, transferType)),
3967 sRef_showAliasInfo (fref);
3983 checkMetaStateConsistent (/*@exposed@*/ sRef fref, sRef tref,
3984 fileloc loc, /*@unused@*/ transferKind transferType)
3987 ** Checks if it is consistent to leave storage marked as tref in state of fref.
3990 valueTable fvalues = sRef_getValueTable (fref);
3991 valueTable tvalues = sRef_getValueTable (tref);
3993 DPRINTF (("Metastate consistent: %s => %s",
3994 sRef_unparseFull (fref),
3995 sRef_unparseFull (tref)));
3997 if (valueTable_isUndefined (tvalues) || valueTable_isUndefined (fvalues)) {
3998 /* Cannot check without value tables. An error was already detected. */
3999 DPRINTF (("No value table: %s / %s",
4000 bool_unparse (valueTable_isUndefined (tvalues)),
4001 bool_unparse (valueTable_isUndefined (fvalues))));
4005 valueTable_elements (fvalues, fkey, fval) {
4007 metaStateInfo minfo;
4009 DPRINTF (("Transfer: %s", fkey));
4010 tval = valueTable_lookup (tvalues, fkey);
4011 minfo = context_lookupMetaStateInfo (fkey);
4013 if (!stateValue_isDefined (tval))
4015 if (ctype_isUnknown (sRef_getType (fref)))
4017 ; /* Okay, put in default values without knowing type */
4022 DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
4023 sRef_unparseFull (tref),
4029 llassert (metaStateInfo_isDefined (minfo));
4031 if (stateValue_isError (fval) || stateValue_isError (tval))
4035 else if (sRef_isDefinitelyNull (fref)
4036 || usymtab_isDefinitelyNull (fref))
4038 ; /* No errors for null values in state transfers. */
4043 stateCombinationTable sctable = metaStateInfo_getTransferTable (minfo);
4044 cstring msg = cstring_undefined;
4045 int nval = stateCombinationTable_lookup (sctable,
4046 stateValue_getValue (fval),
4047 stateValue_getValue (tval),
4050 if (nval == stateValue_error)
4052 if (transferType == TT_LEAVETRANS)
4056 else if (transferType == TT_GLOBRETURN)
4061 ("Function returns with global %q in inconsistent state (%q is %q, should be %q)%q",
4062 sRef_unparse (sRef_getRootBase (fref)),
4063 sRef_unparse (fref),
4064 stateValue_unparseValue (fval, minfo),
4065 stateValue_unparseValue (tval, minfo),
4066 cstring_isDefined (msg)
4067 ? message (": %s", msg) : cstring_undefined),
4070 sRef_showMetaStateInfo (fref, fkey);
4073 else if (transferType == TT_GLOBPASS)
4078 ("Function called with global %q in inconsistent state (%q is %q, should be %q)%q",
4079 sRef_unparse (sRef_getRootBase (fref)),
4080 stateValue_unparseValue (fval, minfo),
4081 sRef_unparse (fref),
4082 stateValue_unparseValue (tval, minfo),
4083 cstring_isDefined (msg)
4084 ? message (": %s", msg) : cstring_undefined),
4087 sRef_showMetaStateInfo (fref, fkey);
4090 else if (transferType == TT_PARAMRETURN)
4095 ("Function returns with parameter %q in inconsistent state (%q is %q, should be %q)%q",
4096 sRef_unparse (sRef_getRootBase (fref)),
4097 sRef_unparse (fref),
4098 stateValue_unparseValue (fval, minfo),
4099 stateValue_unparseValue (tval, minfo),
4100 cstring_isDefined (msg)
4101 ? message (": %s", msg) : cstring_undefined),
4104 sRef_showMetaStateInfo (fref, fkey);
4112 ("Invalid transfer from %q %x to %q (%q)%q",
4113 stateValue_unparseValue (fval, minfo),
4114 sRef_unparse (fref),
4115 stateValue_unparseValue (tval, minfo),
4116 sRef_unparse (tref),
4117 cstring_isDefined (msg)
4118 ? message (": %s", msg) : cstring_undefined),
4121 sRef_showMetaStateInfo (fref, fkey);
4127 if (stateValue_getValue (fval) != nval)
4129 stateValue_updateValueLoc (fval, nval, loc);
4134 DPRINTF (("Transfer: %s %s -> %s",
4135 fkey, stateValue_unparse (fval), stateValue_unparse (tval)));
4136 } end_valueTable_elements ;
4140 checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref,
4142 fileloc loc, transferKind /*@i32@*/ transferType)
4144 valueTable fvalues = sRef_getValueTable (fref);
4145 valueTable tvalues = sRef_getValueTable (tref);
4147 DPRINTF (("Metastate transfer: from %s", exprNode_unparse (fexp)));
4149 DPRINTF (("Metastate transfer: %s => %s",
4150 sRef_unparseFull (fref),
4151 sRef_unparseFull (tref)));
4153 if (valueTable_isUndefined (tvalues) || valueTable_isUndefined (fvalues)) {
4154 /* Cannot check without value tables. An error was already detected. */
4155 DPRINTF (("No value table: %s / %s",
4156 bool_unparse (valueTable_isUndefined (tvalues)),
4157 bool_unparse (valueTable_isUndefined (fvalues))));
4161 valueTable_elements (fvalues, fkey, fval) {
4163 metaStateInfo minfo;
4164 stateCombinationTable sctable;
4168 DPRINTF (("Transfer: %s", fkey));
4169 tval = valueTable_lookup (tvalues, fkey);
4170 minfo = context_lookupMetaStateInfo (fkey);
4172 if (!stateValue_isDefined (tval))
4174 if (ctype_isUnknown (sRef_getType (fref)))
4176 ; /* Okay, put in default values without knowing type */
4181 DPRINTF (("Metastate transfer: %s => %s",
4182 exprNode_unparse (fexp), exprNode_unparse (texp)));
4183 DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
4184 sRef_unparseFull (tref),
4190 llassert (metaStateInfo_isDefined (minfo));
4192 if (stateValue_isError (fval))
4196 else if (stateValue_isError (tval))
4198 if (sRef_isLocalVar (tref) && transferType == TT_DOASSIGN)
4200 /* Local assignments just replace state. */
4201 stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
4202 DPRINTF (("Update: %s", stateValue_unparse (tval)));
4204 else if (transferType == TT_FCNRETURN)
4206 ; /* Returning from an unannotated function */
4210 DPRINTF (("Transfer to error: %s / %s", sRef_unparseFull (tref),
4211 transferType_unparse (transferType)));
4216 DPRINTF (("Check: %s / %s / %s / %s", fkey,
4217 metaStateInfo_unparse (minfo),
4218 stateValue_unparse (fval),
4219 stateValue_unparse (tval)));
4221 sctable = metaStateInfo_getTransferTable (minfo);
4222 msg = cstring_undefined;
4224 nval = stateCombinationTable_lookup (sctable,
4225 stateValue_getValue (fval),
4226 stateValue_getValue (tval),
4229 if (transferType == TT_DOASSIGN && sRef_isLocalVar (tref))
4231 /* Local assignments just replace state. */
4232 DPRINTF (("No transfer error assigning to local: %s", msg));
4233 stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
4234 DPRINTF (("Update: %s", stateValue_unparse (tval)));
4238 if (nval == stateValue_error)
4240 /*@i32 print extra info for assignments@*/
4245 ("Invalid transfer from %q %x to %q%q: %q",
4246 stateValue_unparseValue (fval, minfo),
4247 sRef_unparse (fref),
4248 stateValue_unparseValue (tval, minfo),
4249 cstring_isDefined (msg)
4250 ? message (" (%s)", msg) : cstring_undefined,
4251 transferErrorExcerpt (transferType, fexp, texp, fcn)),
4254 sRef_showMetaStateInfo (fref, fkey);
4255 sRef_showMetaStateInfo (tref, fkey);
4259 DPRINTF (("Suppressed transfer error: %s", msg));
4264 if (transferType == TT_FCNRETURN)
4267 ** Returning this reference from a function, mark this reference
4268 ** so no lost reference errors are returned.
4271 stateValue_updateValueLoc (fval, stateValue_error, loc);
4273 else if (stateValue_getValue (fval) != nval)
4275 stateValue_updateValueLoc (fval, nval, loc);
4286 DPRINTF (("Transfer: %s %s -> %s",
4287 fkey, stateValue_unparse (fval), stateValue_unparse (tval)));
4288 } end_valueTable_elements ;
4292 ** assigns fexp := tref or passes fexp as a parameter, or returns fexp.
4294 ** For assignments, sets alias and definition state accordingly.
4298 checkTransfer (exprNode fexp, /*@dependent@*/ sRef fref,
4299 exprNode texp, /*@dependent@*/ sRef tref,
4301 fileloc loc, transferKind transferType)
4305 if (context_inProtectVars ())
4310 DPRINTF (("Check transfer: %s => %s",
4311 sRef_unparse (fref),
4312 sRef_unparse (tref)));
4313 DPRINTF (("Check transfer: %s => %s",
4314 exprNode_unparse (fexp),
4315 exprNode_unparse (texp)));
4317 checkMetaStateTransfer (fexp, fref, texp, tref, fcn,
4321 ** for local references, we need to check
4322 ** the transfer for all possible aliases.
4325 if (sRef_isLocalVar (tref) && transferType != TT_DOASSIGN)
4327 sRefSet alias = usymtab_allAliases (tref);
4329 sRefSet_realElements (alias, atref)
4331 sRef abase = sRef_getRootBase (atref);
4333 if (sRef_isKnown (atref)
4334 && !sRef_isLocalVar (abase)
4335 && !sRef_isExternal (abase))
4337 atref = sRef_updateSref (atref);
4339 if (sRef_hasName (atref))
4341 if (!sRef_isNew (atref)
4342 && !sRef_sameName (tref, atref))
4344 context_setAliasAnnote (atref, tref);
4347 checkTransferAux (fexp, fref, TRUE,
4351 context_clearAliasAnnote ();
4354 } end_sRefSet_realElements;
4356 sRefSet_free (alias);
4359 if (sRef_isLocalVar (fref))
4361 sRefSet alias = usymtab_allAliases (fref);
4363 sRefSet_realElements (alias, afref)
4365 sRef abase = sRef_getRootBase (afref);
4367 if (sRef_isKnown (afref)
4368 && !sRef_isLocalVar (abase)
4369 && !sRef_isExternal (abase))
4371 afref = sRef_updateSref (afref);
4373 if (sRef_hasName (afref))
4375 if (!sRef_isNew (afref)
4376 && !sRef_sameName (afref, fref))
4378 context_setAliasAnnote (afref, fref);
4381 checkTransferAux (fexp, afref, FALSE,
4385 context_clearAliasAnnote ();
4388 } end_sRefSet_realElements;
4390 sRefSet_free (alias);
4394 checkTransferAux (fexp, fref, FALSE, texp, tref, FALSE,
4399 static /*@exposed@*/ sRef
4400 dependentReference (sRef sr)
4402 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4404 DPRINTF (("Dependent reference: %s", sRef_unparse (sr)));
4405 DPRINTF (("Aliases: %s", sRefSet_unparse (ab)));
4408 ** If there is a local variable that aliases sr, then there is no
4409 ** error. Make the local an only.
4412 if (!sRefSet_isEmpty (ab))
4414 sRef res = sRef_undefined;
4416 DPRINTF (("Here we are!"));
4419 ** make one an only, others alias it
4422 sRefSet_realElements (ab, current)
4424 if (sRef_isOwned (current))
4429 } end_sRefSet_realElements;
4431 if (sRef_isInvalid (res))
4434 ** evans - 2001-03-24
4435 ** No owned element, just choose one!
4436 ** (Any reason for preference?)
4439 res = sRefSet_choose (ab);
4446 return sRef_undefined;
4449 bool transferChecks_canLoseReference (/*@dependent@*/ sRef sr, fileloc loc)
4451 bool gotone = FALSE;
4452 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4455 ** if there is a local variable that aliases sr, then there is no
4456 ** error. Make the local an only.
4459 if (!sRefSet_isEmpty (ab))
4462 ** make one an only, others alias it
4465 sRefSet_realElements (ab, current)
4467 sRef_setLastReference (current, sr, loc);
4470 } end_sRefSet_realElements;
4478 bool canLoseLocalReference (/*@dependent@*/ sRef sr, fileloc loc)
4480 bool gotone = FALSE;
4481 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4484 ** if there is a local variable that aliases sr, then there is no
4485 ** error. Make the local an only.
4488 if (!sRefSet_isEmpty (ab))
4491 ** make one an only, others alias it
4494 sRefSet_realElements (ab, current)
4496 if (sRef_isRealLocalVar (sRef_getRootBase (current)))
4498 sRef_setLastReference (current, sr, loc);
4502 } end_sRefSet_realElements;