2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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://www.splint.org
28 # include "lclintMacros.nf"
30 # include "transferChecks.h"
32 static void checkStructTransfer (exprNode p_lhs, sRef p_slhs, exprNode p_rhs, sRef p_srhs,
33 fileloc p_loc, transferKind p_tt);
34 static void checkMetaStateConsistent (/*@exposed@*/ sRef p_fref, sRef p_tref,
35 fileloc p_loc, transferKind p_transferType) ;
37 static void checkLeaveTrans (uentry p_actual, transferKind p_transferType);
38 static void checkTransfer (exprNode p_fexp, /*@dependent@*/ sRef p_fref,
39 exprNode p_texp, /*@dependent@*/ sRef p_tref,
40 exprNode p_fcn, /* for printing better error messages */
41 fileloc p_loc, transferKind p_transferType);
42 static void checkGlobTrans (uentry p_glob, transferKind p_type);
45 checkCompletelyDefined (exprNode p_fexp, /*@exposed@*/ sRef p_fref, sRef p_ofref,
46 exprNode p_texp, sRef p_tref,
47 bool p_topLevel, bool p_inUnion, bool p_directUnion,
48 fileloc p_loc, transferKind p_transferType, int p_depth,
51 static /*@exposed@*/ sRef dependentReference (sRef p_sr);
52 static bool canLoseLocalReference (/*@dependent@*/ sRef p_sr, fileloc p_loc) ;
55 ** returns the most specific alkind
58 alkind alkind_resolve (alkind a1, alkind a2)
60 if (a1 == AK_UNKNOWN || a1 == AK_ERROR) return a2;
61 if (a2 == AK_UNKNOWN || a2 == AK_ERROR || a2 == AK_LOCAL) return a1;
62 if (a1 == AK_LOCAL) return a2;
70 ** FCNRETURN return fref; tref is return type
71 ** GLOBASSIGN tref = fref;
72 ** FCNPASS call (fref) ; tref is the argument type
76 static /*@only@*/ cstring
77 transferErrorMessage (transferKind transferType, alkind tkind) /*@*/
82 return (message ("returned as %s", alkind_unparse (tkind)));
84 return (message ("assigned to %s", alkind_unparse (tkind)));
86 return (message ("assigned to %s", alkind_unparse (tkind)));
88 return (message ("used as initial value for %s",
89 alkind_unparse (tkind)));
91 return (message ("passed as %s param", alkind_unparse (tkind)));
97 static /*@only@*/ cstring
98 transferErrorExcerpt (transferKind transferType, exprNode fexp, exprNode texp, exprNode fcn) /*@*/
100 switch (transferType)
103 return (message ("return %s", exprNode_unparse (fexp)));
107 return (message ("%s = %s", exprNode_unparse (texp), exprNode_unparse (fexp)));
109 if (exprNode_isDefined (fcn))
111 return message ("%s(..., %s, ...)",
112 exprNode_unparse (fcn),
113 exprNode_unparse (fexp));
117 return cstring_copy (exprNode_unparse (fexp));
125 transferErrorExpMessage (transferKind transferType, exkind tkind) /*@*/
127 if (exkind_isUnknown (tkind))
129 switch (transferType)
132 return (cstring_makeLiteral ("returned without qualification"));
135 return (cstring_makeLiteral ("assigned to unqualified reference"));
137 return (cstring_makeLiteral ("passed without qualification"));
139 return (cstring_makeLiteral ("used as initial value for unqualified storage"));
145 switch (transferType)
148 return (message ("returned as %s", exkind_unparse (tkind)));
151 return (message ("assigned to %s", exkind_unparse (tkind)));
153 return (message ("passed as %s param", exkind_unparse (tkind)));
161 static /*@observer@*/ cstring
162 transferNullMessage (transferKind transferType) /*@*/
164 switch (transferType)
167 return (cstring_makeLiteralTemp ("returned as non-null"));
170 return (cstring_makeLiteralTemp ("assigned to non-null"));
172 return (cstring_makeLiteralTemp ("initialized to non-null"));
174 return (cstring_makeLiteralTemp ("passed as non-null param"));
180 static /*@dependent@*/ exprNode atFunction = exprNode_undefined;
181 static int atArgNo = 0;
182 static int atNumArgs = 0;
184 static cstring generateText (exprNode e1, exprNode e2,
185 sRef tref, transferKind tt)
188 if (tt == TT_DOASSIGN || tt == TT_GLOBINIT)
190 return (message ("%s = %s", exprNode_unparse (e2),
191 exprNode_unparse (e1)));
193 else if (tt == TT_FIELDASSIGN)
195 return (message ("%s = %s (field %q)",
196 exprNode_unparse (e2),
197 exprNode_unparse (e1),
198 sRef_unparse (tref)));
200 else if (tt == TT_FCNPASS)
202 return (message ("%s (%s%s%s)",
203 exprNode_unparse (atFunction),
204 (atArgNo == 1 ? cstring_undefined
205 : cstring_makeLiteralTemp ("..., ")),
206 exprNode_unparse (e1),
207 (atArgNo == atNumArgs ? cstring_undefined
208 : cstring_makeLiteralTemp (", ..."))));
212 return (cstring_copy (exprNode_unparse (e1)));
216 static /*@observer@*/ cstring
217 transferType_unparse (transferKind transferType) /*@*/
219 switch (transferType)
222 return (cstring_makeLiteralTemp ("Returned"));
225 return (cstring_makeLiteralTemp ("Assigned"));
227 return (cstring_makeLiteralTemp ("Passed"));
229 return (cstring_makeLiteralTemp ("Initialized"));
231 return (cstring_makeLiteralTemp ("GLOB RETURN!"));
233 return (cstring_makeLiteralTemp ("GLOB PASS!"));
235 return (cstring_makeLiteralTemp ("PARAM RETURN!"));
237 return (cstring_makeLiteralTemp ("LEAVE TRANS!"));
243 static /*@observer@*/ cstring udError (sRef s)
247 return cstring_makeLiteralTemp ("released");
249 else if (sRef_isAllocated (s))
251 return cstring_makeLiteralTemp ("allocated but not defined");
255 return cstring_makeLiteralTemp ("undefined");
260 cstring defExpl (sRef s) /*@*/
262 sRef rb = sRef_getRootBase (s);
264 if (sRef_sameName (rb, s))
266 if (sRef_isAllocated (s))
268 return cstring_makeLiteral (" (allocated only)");
270 return cstring_undefined;
274 return (message (" (%q is %s)", sRef_unparse (s), udError (s)));
280 ** More than just definition checking --- checks for consistent state also!
282 ** Returns TRUE if fref is completely defined.
283 ** if !report, returns TRUE unless error is at the deep level.
287 checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
288 exprNode texp, sRef tref,
289 bool topLevel, bool inUnion, bool directUnion,
290 fileloc loc, transferKind transferType,
291 int depth, bool report)
294 alkind fkind = sRef_getAliasKind (fref);
295 alkind tkind = sRef_getAliasKind (tref);
297 DPRINTF (("Check completely defined: %s [%s] / %s [%s]",
298 exprNode_unparse (fexp), sRef_unparseFull (fref),
299 exprNode_unparse (texp), sRef_unparseFull (tref)));
301 if (depth > MAXDEPTH)
305 ("Check definition limit exceeded, checking %q. "
306 "This either means there is a variable with at least "
307 "%d indirections apparent in the program text, or "
308 "there is a bug in Splint.",
315 if (!sRef_isKnown (fref))
320 if (sRef_isDead (fref))
322 DPRINTF (("Dead storage to completely defined: %s", sRef_unparseFull (fref)));
325 if (alkind_isStack (fkind))
327 ctype rt = ctype_realType (sRef_getType (tref));
329 if (ctype_isMutable (rt) && !ctype_isSU (rt))
331 if (transferType == TT_PARAMRETURN)
336 ("Stack-allocated storage %qreachable from parameter %q",
337 sRef_unparseOpt (fref),
338 sRef_unparse (ofref)),
341 sRef_showAliasInfo (fref);
344 else if (transferType == TT_GLOBRETURN)
349 ("Stack-allocated storage %qreachable from global %q",
350 sRef_unparseOpt (fref),
351 sRef_unparse (ofref)),
354 sRef_showAliasInfo (fref);
357 else if (transferType == TT_FCNRETURN)
362 ("Stack-allocated storage %qreachable from return value: %s",
363 sRef_unparseOpt (fref),
364 exprNode_unparse (fexp)),
367 sRef_showAliasInfo (fref);
379 DPRINTF (("From: %s ==> %s",
380 sRef_unparseFull (fref),
381 sRef_unparseFull (tref)));
383 checkMetaStateConsistent (fref, tref, loc, transferType);
385 if ((sRef_isObserver (fref) && !sRef_isObserver (tref))
386 || (sRef_isExposed (fref) && !(sRef_isObserver (tref)
387 || sRef_isExposed (tref))))
389 flagcode code = (sRef_isObserver (fref)
390 ? FLG_OBSERVERTRANS : FLG_EXPOSETRANS);
392 if (!sRef_isStateLive (fref))
394 ; /* no error (will be a definition error) */
396 else if (transferType == TT_DOASSIGN
397 || transferType == TT_FIELDASSIGN
398 || transferType == TT_GLOBINIT
399 || transferType == TT_FCNPASS)
403 else if (transferType == TT_PARAMRETURN)
408 ("%s storage %qreachable from %s parameter",
409 exkind_capName (sRef_getExKind (fref)),
410 sRef_unparseOpt (fref),
411 exkind_unparseError (sRef_getExKind (tref))),
414 sRef_showExpInfo (fref);
415 sRef_setExKind (fref, XO_UNKNOWN, loc);
418 else if (transferType == TT_LEAVETRANS)
422 else if (transferType == TT_GLOBINIT)
427 ("%s storage %qreachable from %s initial value",
428 exkind_capName (sRef_getExKind (fref)),
429 sRef_unparseOpt (fref),
430 exkind_unparseError (sRef_getExKind (tref))),
433 sRef_showExpInfo (fref);
434 sRef_setExKind (fref, XO_UNKNOWN, loc);
437 else if (transferType == TT_GLOBRETURN)
442 ("%s storage %qreachable from %s global",
443 exkind_capName (sRef_getExKind (fref)),
444 sRef_unparseOpt (fref),
445 exkind_unparseError (sRef_getExKind (tref))),
448 sRef_showExpInfo (fref);
449 sRef_setExKind (fref, XO_UNKNOWN, loc);
452 else if (transferType == TT_FCNRETURN)
457 ("%s storage %qreachable from %s return value",
458 exkind_capName (sRef_getExKind (fref)),
459 sRef_unparseOpt (fref),
460 exkind_unparseError (sRef_getExKind (tref))),
463 sRef_showExpInfo (fref);
464 sRef_setExKind (fref, XO_UNKNOWN, loc);
469 llcontbug (message ("Transfer type: %s",
470 transferType_unparse (transferType)));
475 ("%s storage %qreachable from %s return value",
476 exkind_capName (sRef_getExKind (fref)),
477 sRef_unparseOpt (fref),
478 exkind_unparseError (sRef_getExKind (tref))),
481 sRef_showExpInfo (fref);
482 sRef_setExKind (fref, XO_UNKNOWN, loc);
488 if (!alkind_compatible (fkind, tkind))
490 if (fkind == AK_UNKNOWN && !sRef_isStateLive (fref))
492 ; /* no error (will be a definition error) */
494 else if (transferType == TT_DOASSIGN)
498 else if (transferType == TT_FCNPASS)
500 if (alkind_isKnown (sRef_getAliasKind (tref)))
505 ("Storage %qreachable from passed parameter "
506 "is %s (should be %s): %s",
507 sRef_unparseOpt (fref),
508 alkind_unparse (sRef_getAliasKind (fref)),
509 alkind_unparse (sRef_getAliasKind (tref)),
510 exprNode_unparse (fexp)),
513 sRef_showAliasInfo (fref);
517 else if (transferType == TT_PARAMRETURN)
519 bool noerror = FALSE;
521 if (alkind_isDependent (sRef_getAliasKind (fref)))
523 if (canLoseLocalReference (fref, loc))
533 ("Storage %qreachable from parameter is %s (should be %s)",
534 sRef_unparseOpt (fref),
535 alkind_unparse (sRef_getAliasKind (fref)),
536 alkind_unparse (sRef_getAliasKind (tref))),
539 sRef_showAliasInfo (fref);
542 else if (transferType == TT_LEAVETRANS)
547 ("Storage %qreachable from temporary reference is %s "
548 "at scope exit (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_GLOBRETURN)
562 ("Storage %qreachable from global is %s (should be %s)",
563 sRef_unparseOpt (fref),
564 alkind_unparse (sRef_getAliasKind (fref)),
565 alkind_unparse (sRef_getAliasKind (tref))),
568 sRef_showAliasInfo (fref);
571 else if (transferType == TT_FCNRETURN)
576 ("Storage %qreachable from return value is %s (should be %s)",
577 sRef_unparseOpt (fref),
578 alkind_unparse (sRef_getAliasKind (fref)),
579 alkind_unparse (sRef_getAliasKind (tref))),
582 sRef_showAliasInfo (fref);
585 else if (transferType == TT_GLOBINIT)
590 ("Storage %qreachable from initial value is %s (should be %s)",
591 sRef_unparseOpt (fref),
592 alkind_unparse (sRef_getAliasKind (fref)),
593 alkind_unparse (sRef_getAliasKind (tref))),
596 sRef_showAliasInfo (fref);
601 llcontbug (message ("Transfer type: %s",
602 transferType_unparse (transferType)));
607 ("Storage %qreachable from return value is %s (should be %s)",
608 sRef_unparseOpt (fref),
609 alkind_unparse (sRef_getAliasKind (fref)),
610 alkind_unparse (sRef_getAliasKind (tref))),
613 sRef_showAliasInfo (fref);
618 if (sRef_isDead (fref))
625 if (transferType == TT_PARAMRETURN)
630 ("Released storage %q reachable from parameter at return point",
631 sRef_unparse (fref)),
634 sRef_showStateInfo (fref);
638 else if (transferType == TT_LEAVETRANS)
642 message ("Released storage %q reachable from temporary "
643 "reference at scope exit",
644 sRef_unparse (fref)),
647 sRef_showStateInfo (fref);
651 else if (transferType == TT_GLOBRETURN)
655 message ("Released storage %q reachable from global",
656 sRef_unparse (fref)),
659 sRef_showStateInfo (fref);
663 else if (transferType == TT_FCNPASS)
667 message ("Released storage %q reachable from passed parameter",
668 sRef_unparse (fref)),
671 sRef_showStateInfo (fref);
679 message ("Released storage %q reachable from parameter",
680 sRef_unparse (fref)),
683 sRef_showStateInfo (fref);
691 && sRef_possiblyNull (fref)
692 && !sRef_perhapsNull (tref)
693 && ctype_isRealPointer (sRef_getType (tref))
694 && !usymtab_isGuarded (fref))
696 if (transferType == TT_FCNRETURN)
700 message ("%q storage %qderivable from return value: %s",
701 cstring_capitalize (sRef_nullMessage (fref)),
702 sRef_unparseOpt (fref),
703 exprNode_unparse (fexp)),
706 sRef_showNullInfo (fref);
708 DPRINTF (("fref: %s", sRef_unparseFull (fref)));
709 DPRINTF (("tref: %s", sRef_unparseFull (tref)));
711 sRef_setNullError (fref);
714 else if (transferType == TT_GLOBRETURN || transferType == TT_PARAMRETURN)
719 ("Function returns with %s storage derivable from %q %q",
720 sRef_nullMessage (fref),
721 cstring_makeLiteral ((transferType == TT_GLOBRETURN)
722 ? "global" : "parameter"),
723 sRef_unparse (fref)),
726 sRef_showNullInfo (fref);
727 sRef_setNullError (fref);
730 else if (transferType == TT_GLOBPASS)
734 message ("Function called with %s storage "
735 "derivable from global %q",
736 sRef_nullMessage (fref),
737 sRef_unparse (fref)),
740 sRef_showNullInfo (fref);
741 sRef_setNullError (fref);
744 else if (transferType == TT_FCNPASS)
748 message ("%q storage %qderivable from parameter %q",
749 cstring_capitalize (sRef_nullMessage (fref)),
750 sRef_unparseOpt (fref),
751 generateText (fexp, exprNode_undefined,
752 sRef_undefined, TT_FCNPASS)),
755 DPRINTF (("fref: %s", sRef_unparseFull (fref)));
756 DPRINTF (("tref: %s", sRef_unparseFull (tref)));
757 sRef_showNullInfo (fref);
758 sRef_setNullError (fref);
763 llassert (transferType == TT_DOASSIGN
764 || transferType == TT_GLOBINIT
765 || transferType == TT_LEAVETRANS);
769 if (sRef_isRelDef (tref)
770 || sRef_isPartial (tref)
771 || sRef_isAllocated (tref)
772 || sRef_isStateSpecial (tref))
774 /* should check fref is allocated? */
778 ct = ctype_realType (sRef_getType (fref));
780 DPRINTF (("Here: %s", ctype_unparse (ct)));
782 if (!(sRef_isAnyDefined (fref)
783 || sRef_isPdefined (fref)
784 || sRef_isAllocated (fref)
785 || sRef_isStateUnknown (fref)))
787 if (transferType == TT_GLOBRETURN)
792 message ("Function returns with global %q not "
793 "completely defined%q",
794 sRef_unparse (sRef_getRootBase (fref)),
798 sRef_showStateInfo (fref);
799 sRef_setDefined (fref, loc);
802 else if (transferType == TT_GLOBPASS)
808 ("Function called with global %q not completely defined%q",
809 sRef_unparse (sRef_getRootBase (fref)),
813 sRef_showStateInfo (fref);
814 sRef_setDefined (fref, loc);
817 else if (transferType == TT_PARAMRETURN)
819 if (report && !topLevel
822 message ("Function returns storage %q reachable from parameter not "
823 "completely defined%q",
824 sRef_unparse (ofref),
828 sRef_showStateInfo (fref);
829 sRef_setDefined (fref, loc);
832 else if (transferType == TT_LEAVETRANS)
834 if (report && !topLevel
837 message ("Scope exits with storage %q reachable from "
838 "temporary reference not completely defined%q",
839 sRef_unparse (ofref),
843 sRef_showStateInfo (fref);
844 sRef_setDefined (fref, loc);
849 if (transferType != TT_DOASSIGN
850 && (!(sRef_isNew (fref) || sRef_isType (fref))))
854 DPRINTF (("Here we are: %s", sRef_unparseFull (fref)));
856 if (sRef_isDead (fref))
860 message ("%s storage %qwas released: %q",
861 transferType_unparse (transferType),
862 sRef_unparseOpt (fref),
863 generateText (fexp, texp, tref, transferType)),
866 sRef_showStateInfo (fref);
874 ("%s storage %qnot completely defined%q: %q",
875 transferType_unparse (transferType),
876 sRef_unparseOpt (ofref),
878 generateText (fexp, texp, tref, transferType)),
881 sRef rb = sRef_getRootBase (fref);
882 sRef_showStateInfo (fref);
884 DPRINTF (("fref: %s", sRef_unparseFull (fref)));
885 DPRINTF (("rb: %s", sRef_unparseFull (rb)));
886 sRef_setDefinedComplete (rb, loc);
894 if (sRef_isAllocated (fref) && sRef_isValid (tref)
895 && (transferType == TT_DOASSIGN))
897 sRef_setAllocatedComplete (tref, loc);
906 if (ctype_isUnknown (ct))
910 else if (ctype_isPointer (ct) || ctype_isArray (ct)) /* evans 2001-07-12 added ctype_isArray */
912 ctype tct = ctype_realType (sRef_getType (tref));
914 if (sRef_isStateUnknown (fref))
920 DPRINTF (("Here fref: %s", sRef_unparseFull (fref)));
921 DPRINTF (("Here tref: %s", sRef_unparseFull (tref)));
923 if (ctype_isAP (tct) || ctype_isUnknown (tct))
925 sRef fptr = sRef_constructDeref (fref);
926 sRef tptr = sRef_constructDeref (tref);
928 DPRINTF (("Here tptr: %s", sRef_unparseFull (tptr)));
930 return (checkCompletelyDefined (fexp, fptr, ofref,
932 FALSE, inUnion, FALSE, loc,
933 transferType, depth + 1, report));
941 else if (ctype_isStruct (ct))
943 ctype tct = ctype_realType (sRef_getType (tref));
945 DPRINTF (("Struct defined: %s", ctype_unparse (tct)));
947 if (ctype_match (ct, tct))
950 bool hasOneDefined = FALSE;
951 cstringSList badFields = cstringSList_undefined;
953 if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref))
958 DPRINTF (("Check field: %s", sRef_unparseFull (fref)));
960 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
962 DPRINTF (("Is defined: %s", sRef_unparse (fref)));
964 sRefSet_realElements (sRef_derivedFields (fref), sr)
968 hasOneDefined = TRUE;
970 DPRINTF (("Check derived: %s", sRef_unparseFull (sr)));
972 if (sRef_isField (sr))
974 cstring fieldname = sRef_getField (sr);
975 sRef fldref = sRef_makeField (tref, fieldname);
976 bool shouldCheck = !sRef_isRecursiveField (fldref);
982 (checkCompletelyDefined (fexp, sr, ofref,
984 FALSE, inUnion, FALSE, loc,
985 transferType, depth + 1,
996 badFields = cstringSList_add (badFields,
1000 } end_sRefSet_realElements;
1002 else if (sRef_isAllocated (fref))
1005 ** for structures, each field must be completely defined
1008 uentryList fields = ctype_getFields (ct);
1010 uentryList_elements (fields, ue)
1013 cstring name = uentry_getRealName (ue);
1014 sRef ffield = sRef_makeField (fref, name);
1015 sRef tfield = sRef_makeField (tref, name);
1016 bool shouldCheck = !sRef_isRecursiveField (tfield);
1024 thisField = ynm_toBoolRelaxed
1025 (checkCompletelyDefined (fexp, ffield, ofref,
1027 FALSE, inUnion, FALSE,
1035 badFields = cstringSList_add (badFields, uentry_rawName (ue));
1039 hasOneDefined = TRUE;
1041 } end_uentryList_elements;
1045 DPRINTF (("Not checking: %s", sRef_unparseFull (fref)));
1048 if (!isOk && (!inUnion || hasOneDefined))
1050 if (transferType == TT_GLOBRETURN)
1054 message ("Global storage %q contains %d undefined field%& "
1055 "when call returns: %q",
1056 sRef_unparse (fref),
1057 cstringSList_size (badFields),
1058 cstringSList_unparseAbbrev (badFields)),
1061 sRef_setDefined (fref, loc);
1064 else if (transferType == TT_GLOBPASS)
1068 message ("Global storage %q contains %d undefined field%& "
1070 sRef_unparse (fref),
1071 cstringSList_size (badFields),
1072 cstringSList_unparseAbbrev (badFields)),
1075 sRef_setDefined (fref, loc);
1078 else if (transferType == TT_PARAMRETURN)
1082 message ("Storage %qreachable from parameter "
1083 "contains %d undefined field%&: %q",
1084 sRef_unparseOpt (fref),
1085 cstringSList_size (badFields),
1086 cstringSList_unparseAbbrev (badFields)),
1089 sRef_setDefined (fref, loc);
1092 else if (transferType == TT_LEAVETRANS)
1100 message ("%s storage %qcontains %d undefined field%&: %q",
1101 transferType_unparse (transferType),
1102 sRef_unparseOpt (fref),
1103 cstringSList_size (badFields),
1104 cstringSList_unparseAbbrev (badFields)),
1107 sRef_setDefined (fref, loc);
1112 cstringSList_free (badFields);
1118 return (ynm_fromBool (hasOneDefined));
1127 return (ynm_fromBool (!report || isOk));
1135 else if (ctype_isUnion (ct))
1137 if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref))
1143 ctype tct = ctype_realType (sRef_getType (tref));
1145 if (ctype_isKnown (tct) && ctype_match (ct, tct))
1147 cstringSList goodFields = cstringSList_new ();
1149 int nelements = sRefSet_size (sRef_derivedFields (fref));
1152 ** for unions, at least one field must be completely defined
1155 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
1160 sRefSet_realElements (sRef_derivedFields (fref), sr)
1164 if (sRef_isField (sr))
1166 sRef fldref = sRef_makeField (tref, sRef_getField (sr));
1168 DPRINTF (("Trying union field: %s", sRef_unparseFull (fldref)));
1170 thisField = ynm_toBoolStrict
1171 (checkCompletelyDefined
1173 texp, fldref, FALSE, inUnion,
1174 (nelements > 1 ? TRUE : FALSE),
1175 loc, transferType, depth + 1, FALSE));
1179 goodFields = cstringSList_add
1180 (goodFields, sRef_getField (sr));
1183 } end_sRefSet_realElements;
1185 if (cstringSList_empty (goodFields)
1187 && context_getFlag (FLG_UNIONDEF))
1191 if (transferType == TT_PARAMRETURN)
1195 message ("Union %q reachable from parameter has "
1197 sRef_unparse (fref)),
1200 else if (transferType == TT_LEAVETRANS)
1204 message ("Union %q has no defined field at scope exit",
1205 sRef_unparse (fref)),
1208 /* evans 2001-08-21: added this branch for global returns */
1209 else if (transferType == TT_GLOBRETURN)
1213 message ("Union %q reachable from global %q has "
1215 sRef_unparse (fref),
1216 sRef_unparse (sRef_getRootBase (fref))),
1219 else if (transferType == TT_DOASSIGN
1220 || transferType == TT_FIELDASSIGN
1221 || transferType == TT_GLOBINIT)
1229 message ("%s union %q has no defined field",
1230 transferType_unparse (transferType),
1231 sRef_unparse (fref)),
1238 cstringSList_free (goodFields);
1239 return ynm_fromBool (!report || isOk);
1252 ** fref is being free'd
1256 DSC_GLOB, DSC_LOCAL, DSC_PARAM, DSC_STRUCT
1259 static /*@observer@*/ cstring dscCode_unparse (dscCode desc) /*@*/
1264 return cstring_makeLiteralTemp ("killed global");
1266 return cstring_makeLiteralTemp ("variable declared in this scope");
1268 return cstring_makeLiteralTemp ("released storage");
1270 return cstring_makeLiteralTemp ("released structure parameter");
1277 checkCompletelyDestroyed (exprNode p_fexp, sRef p_fref, bool p_topLevel,
1278 fileloc p_loc, int p_depth, dscCode p_desc,
1281 bool checkGlobalDestroyed (sRef fref, fileloc loc)
1283 return (checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1284 loc, 0, DSC_GLOB, FALSE));
1287 void checkLocalDestroyed (sRef fref, fileloc loc)
1289 if (sRef_isObserver (fref) || sRef_isExposed (fref)
1290 || sRef_isPartial (fref))
1296 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1297 loc, 0, DSC_LOCAL, FALSE);
1301 void checkStructDestroyed (sRef fref, fileloc loc)
1303 DPRINTF (("Check struct destroyed: %s", sRef_unparse (fref)));
1305 if (sRef_isObserver (fref) || sRef_isExposed (fref)
1306 || sRef_isPartial (fref))
1308 DPRINTF (("Its exposed!"));;
1312 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1313 loc, 0, DSC_STRUCT, FALSE);
1318 checkCompletelyDestroyed (exprNode fexp, sRef fref, bool topLevel,
1319 fileloc loc, int depth,
1320 dscCode desc, bool hideErrors)
1324 DPRINTF (("Check completely destroyed: %s", sRef_unparseFull (fref)));
1326 if (depth > MAXDEPTH)
1328 llquietbug (message ("checkCompletelyDestroyed: too deep: %s / %q",
1329 exprNode_unparse (fexp),
1330 sRef_unparseFull (fref)));
1334 if (!sRef_isKnown (fref)) return TRUE;
1336 /* evans 2001-03-24: added this. Definitely null values are always destroyed. */
1338 if (sRef_isDefinitelyNull (fref))
1343 if (sRef_isDependent (fref) || sRef_isShared (fref) || sRef_isKept (fref))
1350 ** evans 2001-03-24: if there is a dependent reference to this storage,
1351 ** no need to destroy, but make it responsible.
1354 sRef depRef = dependentReference (fref);
1356 DPRINTF (("Destroyed? %s / %s",
1357 sRef_unparseFull (fref),
1358 sRef_unparseFull (depRef)));
1360 DPRINTF (("Aliases: %s", usymtab_unparseAliases ()));
1362 if (sRef_isValid (depRef))
1365 ** If the referenced storage was not dependent, we make
1366 ** the reference the owner since it must eventually be
1370 if (!sRef_isDependent (depRef))
1372 sRef_setOnly (depRef, loc); /* could be owned? */
1375 sRef_kill (fref, loc);
1380 if (sRef_isPdefined (fref) && !context_getFlag (FLG_STRICTDESTROY))
1382 DPRINTF (("Partial: %s", sRef_unparseFull (fref)));
1383 hideErrors = TRUE; /* Don't report any more errors, but still change ownership. */
1386 if (usymtab_isDefinitelyNull (fref))
1388 DPRINTF (("Probably null!"));
1392 if (!context_getFlag (FLG_COMPDESTROY)) return TRUE;
1393 if (!context_getFlag (FLG_MUSTFREE)) return TRUE;
1395 ct = ctype_realType (sRef_getType (fref));
1397 DPRINTF (("Here: %s", ctype_unparse (ct)));
1401 bool docheck = FALSE;
1404 if (sRef_isFresh (fref) || sRef_isOnly (fref))
1408 DPRINTF (("Here: %s", ctype_unparse (ct)));
1409 if (sRef_isDead (fref)
1410 || sRef_isUnuseable (fref)
1411 || sRef_definitelyNull (fref)
1412 || sRef_isObserver (fref)
1413 || sRef_isExposed (fref))
1421 if (sRef_isPossiblyDead (fref) || sRef_isRelDef (fref))
1423 if (exprNode_isDefined (fexp))
1429 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1430 message ("Only storage %q (type %s) derived from %s "
1431 "may not have been released: %s",
1432 sRef_unparse (fref),
1433 ctype_unparse (sRef_getType (fref)),
1434 dscCode_unparse (desc),
1435 exprNode_unparse (fexp)),
1444 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1446 ("Only storage %q (type %s) derived from %s "
1447 "may not have been released",
1448 sRef_unparse (fref),
1449 ctype_unparse (sRef_getType (fref)),
1450 dscCode_unparse (desc)),
1456 sRef_kill (fref, loc); /* prevent further errors */
1461 if (sRef_isStateUndefined (fref))
1463 DPRINTF (("Here: %s", ctype_unparse (ct)));
1468 if (exprNode_isDefined (fexp))
1470 DPRINTF (("Here: %s", sRef_unparseFull (fref)));
1477 message ("Only storage %q (type %s) derived from %s "
1478 "is not released (memory leak): %s",
1479 sRef_unparse (fref),
1480 ctype_unparse (sRef_getType (fref)),
1481 dscCode_unparse (desc),
1482 exprNode_unparse (fexp)),
1492 message ("Only storage %q (type %s) derived from %s "
1493 "is not released (memory leak)",
1494 sRef_unparse (fref),
1495 ctype_unparse (sRef_getType (fref)),
1496 dscCode_unparse (desc)),
1504 /* sRef_kill (fref, loc); */ /* prevent further errors */
1505 DPRINTF (("Killed: %s", sRef_unparseFull (fref)));
1510 DPRINTF (("Here: %s", ctype_unparse (ct)));
1514 if (/*! evs-2002-03-24 sRef_isAnyDefined (fref) || */
1516 || (sRef_isPdefined (fref)
1517 && sRefSet_isEmpty (sRef_derivedFields (fref))))
1519 DPRINTF (("Here: %s [%s / %s]",
1520 sRef_unparseFull (fref),
1521 bool_unparse (sRef_isAnyDefined (fref)),
1522 bool_unparse (sRef_isDead (fref))));
1527 DPRINTF (("Here..."));
1529 if (ctype_isPointer (ct))
1531 sRef fptr = sRef_constructDeadDeref (fref);
1534 res = checkCompletelyDestroyed (fexp, fptr, FALSE, loc,
1535 depth + 1, desc, hideErrors);
1539 else if (ctype_isArray (ct))
1541 if ((sRef_isStateUnknown (fref) || sRef_isAllocated (fref))
1542 && !sRef_hasDerived (fref))
1545 ** Bogosity necessary to prevent infinite depth.
1552 sRef farr = sRef_constructDeadDeref (fref);
1554 return (checkCompletelyDestroyed (fexp, farr, FALSE, loc,
1555 depth + 1, desc, hideErrors));
1558 else if (ctype_isStruct (ct))
1561 ** for structures, each field must be completely destroyed
1565 uentryList fields = ctype_getFields (ct);
1567 DPRINTF (("Struct fields: %s", uentryList_unparse (fields)));
1569 if (depth >= MAXDEPTH)
1571 llquietbug (message ("checkCompletelyDestroyed (fields): too deep: %s / %q",
1572 exprNode_unparse (fexp),
1573 sRef_unparseFull (fref)));
1579 uentryList_elements (fields, ue)
1581 sRef field = sRef_makeField (fref, uentry_rawName (ue));
1584 ** note order of && operands --- want to report multiple errors
1587 DPRINTF (("Check field: %s", sRef_unparseFull (field)));
1589 isOk = (checkCompletelyDestroyed (fexp, field, FALSE, loc,
1590 depth + 1, desc, hideErrors)
1592 } end_uentryList_elements;
1604 checkReturnTransfer (exprNode fexp, uentry rval)
1606 sRef uref = uentry_getSref (rval);
1607 sRef rref = sRef_makeNew (sRef_getType (uref), uref, cstring_undefined);
1608 uentry fcn = context_getHeader ();
1609 sRef fref = exprNode_getSref (fexp);
1610 stateClauseList clauses = uentry_getStateClauseList (fcn);
1612 DPRINTF (("Check return: %s as %s = %s",
1613 exprNode_unparse (fexp),
1614 sRef_unparseFull (uref),
1615 sRef_unparseFull (rref)));
1617 /* evans 2001-07-18: removed: if (sRef_isStateSpecial (rref)) */
1619 DPRINTF (("Check state clauses: %s",
1620 stateClauseList_unparse (clauses)));
1622 stateClauseList_postElements (clauses, cl)
1624 if (stateClause_isGlobal (cl))
1628 else if (stateClause_setsMetaState (cl))
1630 sRefSet refs = stateClause_getRefs (cl);
1631 qual ql = stateClause_getMetaQual (cl);
1632 annotationInfo ainfo = qual_getAnnotationInfo (ql);
1633 metaStateInfo minfo = annotationInfo_getState (ainfo);
1634 cstring key = metaStateInfo_getName (minfo);
1635 int mvalue = annotationInfo_getValue (ainfo);
1637 DPRINTF (("Return check: %s", stateClause_unparse (cl)));
1639 sRefSet_elements (refs, el)
1641 sRef base = sRef_getRootBase (el);
1643 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
1645 if (sRef_isResult (base))
1647 sRef sr = sRef_fixBase (el, fref);
1649 if (!sRef_checkMetaStateValue (sr, key, mvalue))
1653 message ("Result state %q does not satisfy ensures "
1654 "clause: %q (state is %q, should be %s): %s",
1656 stateClause_unparse (cl),
1657 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
1659 metaStateInfo_unparseValue (minfo, mvalue),
1660 exprNode_unparse (fexp)),
1661 exprNode_loc (fexp)))
1663 sRef_showAliasInfo (sr);
1671 ** Non-results are checked in exit scope.
1674 } end_sRefSet_elements ;
1678 sRefSet refs = stateClause_getRefs (cl);
1679 sRefTest tst = stateClause_getPostTestFunction (cl);
1680 sRefMod modf = stateClause_getReturnEffectFunction (cl);
1682 DPRINTF (("Clause: %s / %s",
1683 stateClause_unparse (cl),
1684 sRefSet_unparse (refs)));
1686 sRefSet_elements (refs, el)
1688 sRef base = sRef_getRootBase (el);
1690 DPRINTF (("el: %s / %s", sRef_unparse (el),
1691 sRef_unparse (base)));
1693 if (sRef_isResult (base))
1695 sRef sr = sRef_fixBase (el, fref);
1697 if (tst != NULL && !(tst (sr)))
1700 (stateClause_postErrorCode (cl),
1701 message ("%s storage %q corresponds to "
1702 "storage %q listed in %q clause: %s",
1703 stateClause_postErrorString (cl, sr),
1706 stateClause_unparseKind (cl),
1707 exprNode_unparse (fexp)),
1708 exprNode_loc (fexp)))
1710 sRefShower ss = stateClause_getPostTestShower (cl);
1721 modf (sr, exprNode_loc (fexp));
1727 ** Non-results are checked in exit scope.
1730 } end_sRefSet_elements ;
1732 } end_stateClauseList_postElements ;
1734 if (ctype_isRealSU (exprNode_getType (fexp)))
1736 sRef ffref = exprNode_getSref (fexp);
1738 checkStructTransfer (exprNode_undefined, rref,
1740 exprNode_loc (fexp),
1745 (void) checkTransfer (fexp, exprNode_getSref (fexp),
1746 exprNode_undefined, rref,
1748 exprNode_loc (fexp), TT_FCNRETURN);
1753 checkPassstateClauseList (uentry ue, exprNode fexp, sRef fref, int argno)
1755 stateClauseList clauses = uentry_getStateClauseList (ue);
1757 DPRINTF (("Check pass special: %s / %s",
1758 exprNode_unparse (fexp), sRef_unparseFull (fref)));
1760 stateClauseList_preElements (clauses, cl)
1762 if (stateClause_isGlobal (cl))
1768 sRefSet refs = stateClause_getRefs (cl);
1769 sRefTest tst = stateClause_getPreTestFunction (cl);
1770 sRefMod modf = stateClause_getEffectFunction (cl);
1772 sRefSet_elements (refs, el)
1774 sRef base = sRef_getRootBase (el);
1776 if (sRef_isResult (base))
1778 ; /* nothing to check before */
1780 else if (sRef_isParam (base))
1782 if (sRef_getParam (base) == argno - 1)
1786 DPRINTF (("Fix base: %s / %s",
1787 sRef_unparseFull (el),
1788 sRef_unparseFull (fref)));
1790 sb = sRef_fixBase (el, fref);
1792 if (tst != NULL && !(tst(sb)))
1795 (stateClause_preErrorCode (cl),
1796 message ("%s storage %qcorresponds to "
1797 "storage listed in %q clause of "
1798 "called function: %s",
1799 stateClause_preErrorString (cl, sb),
1800 sRef_unparseOpt (sb),
1801 stateClause_unparseKind (cl),
1802 exprNode_unparse (fexp)),
1803 exprNode_loc (fexp));
1808 DPRINTF (("Fixing: %s", sRef_unparseFull (sb)));
1809 modf (sb, exprNode_loc (fexp));
1810 DPRINTF (("==> %s", sRef_unparseFull (sb)));
1818 } end_sRefSet_elements ;
1820 } end_stateClauseList_preElements ;
1822 DPRINTF (("After: %s", sRef_unparseFull (fref)));
1826 ** should not modify arg
1830 checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
1831 /*@dependent@*/ exprNode fcn, int argno, int totargs)
1833 sRef tref = uentry_getSref (arg);
1834 sRef fref = exprNode_getSref (fexp);
1836 bool isPartial = FALSE;
1837 bool isImpOut = FALSE;
1838 ctype ct = uentry_getType (arg);
1840 DPRINTF (("Check pass: %s -> %s",
1841 sRef_unparseFull (fref),
1842 sRef_unparseFull (tref)));
1846 atNumArgs = totargs;
1848 if (ctype_isElips (ct))
1853 DPRINTF (("Out arg: %s", bool_unparse (uentry_isOut (arg))));
1855 if (!ctype_isElips (ct) &&
1856 (ctype_isVoidPointer (ct) && uentry_isOut (arg) && sRef_isOnly (tref)))
1858 if (ctype_isRealAP (ct))
1860 if (sRef_aliasCheckSimplePred (sRef_isDead, fref))
1864 message ("Dead storage %qpassed as out parameter to %s: %s",
1865 sRef_unparseOpt (fref),
1866 exprNode_unparse (fcn),
1867 exprNode_unparse (fexp)),
1868 exprNode_loc (fexp)))
1870 if (sRef_isDead (fref))
1872 sRef_showStateInfo (fref);
1876 DPRINTF (("Not really dead!"));
1877 sRef_showStateInfo (fref);
1881 sRef_setAllocated (fref, exprNode_loc (fexp));
1883 else if (context_getFlag (FLG_STRICTUSERELEASED)
1884 && sRef_aliasCheckSimplePred (sRef_isPossiblyDead, fref))
1887 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1888 message ("Possibly dead storage %qpassed as out parameter: %s",
1889 sRef_unparseOpt (fref),
1890 exprNode_unparse (fexp)),
1891 exprNode_loc (fexp)))
1893 if (sRef_isPossiblyDead (fref))
1895 sRef_showStateInfo (fref);
1899 sRef_setAllocated (fref, exprNode_loc (fexp));
1901 else if (sRef_aliasCheckSimplePred (sRef_isStateUndefined, fref)
1902 || sRef_aliasCheckSimplePred (sRef_isUnuseable, fref))
1906 message ("Unallocated storage %qpassed as out parameter: %s",
1907 sRef_unparseOpt (fref),
1908 exprNode_unparse (fexp)),
1909 exprNode_loc (fexp));
1911 sRef_setAllocated (fref, exprNode_loc (fexp));
1919 (void) checkCompletelyDestroyed (fexp, fref, TRUE, exprNode_loc (fexp),
1920 0, DSC_PARAM, FALSE);
1922 /* make it defined now, so checkTransfer is okay */
1923 sRef_setDefined (fref, exprNode_loc (fexp));
1925 else if (uentry_isOut (arg))
1927 DPRINTF (("Here we are!"));
1929 if (ctype_isRealAP (ct)
1930 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1934 message ("Unallocated storage %qpassed as out parameter to %s: %s",
1935 sRef_unparseOpt (fref),
1936 exprNode_unparse (fcn),
1937 exprNode_unparse (fexp)),
1938 exprNode_loc (fexp));
1939 sRef_setAllocated (fref, exprNode_loc (fexp));
1941 else if (sRef_isDead (fref))
1945 message ("Dead storage %qpassed as out parameter to %s: %s",
1946 sRef_unparseOpt (fref),
1947 exprNode_unparse (fcn),
1948 exprNode_unparse (fexp)),
1949 exprNode_loc (fexp)))
1951 sRef_showStateInfo (fref);
1952 sRef_setAllocated (fref, exprNode_loc (fexp));
1955 else if (sRef_isPossiblyDead (fref))
1958 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1959 message ("Possibly dead storage %qpassed as out parameter to %s: %s",
1960 sRef_unparseOpt (fref),
1961 exprNode_unparse (fcn),
1962 exprNode_unparse (fexp)),
1963 exprNode_loc (fexp)))
1965 sRef_showStateInfo (fref);
1966 sRef_setAllocated (fref, exprNode_loc (fexp));
1976 else if (uentry_isPartial (arg))
1978 if (ctype_isRealAP (ct)
1979 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1983 message ("Unallocated storage %qpassed as partial parameter: %s",
1984 sRef_unparseOpt (fref),
1985 exprNode_unparse (fexp)),
1986 exprNode_loc (fexp));
1987 sRef_setAllocated (fref, exprNode_loc (fexp));
1989 else if (sRef_isDead (fref))
1993 message ("Dead storage %qpassed as partial parameter to %s: %s",
1994 sRef_unparseOpt (fref),
1995 exprNode_unparse (fcn),
1996 exprNode_unparse (fexp)),
1997 exprNode_loc (fexp)))
1999 sRef_showStateInfo (fref);
2000 sRef_setAllocated (fref, exprNode_loc (fexp));
2003 else if (sRef_isPossiblyDead (fref))
2006 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
2007 message ("Possibly dead storage %qpassed as partial parameter to %s: %s",
2008 sRef_unparseOpt (fref),
2009 exprNode_unparse (fcn),
2010 exprNode_unparse (fexp)),
2011 exprNode_loc (fexp)))
2013 sRef_showStateInfo (fref);
2014 sRef_setAllocated (fref, exprNode_loc (fexp));
2024 else if (uentry_isStateSpecial (arg))
2026 uentry ue = exprNode_getUentry (fcn);
2028 if (ctype_isRealAP (ct)
2029 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
2033 message ("Unallocated storage %qpassed as special parameter: %s",
2034 sRef_unparseOpt (fref),
2035 exprNode_unparse (fexp)),
2036 exprNode_loc (fexp));
2037 sRef_setAllocated (fref, exprNode_loc (fexp));
2039 else if (sRef_isDead (fref))
2043 message ("Dead storage %qpassed as special parameter to %s: %s",
2044 sRef_unparseOpt (fref),
2045 exprNode_unparse (fcn),
2046 exprNode_unparse (fexp)),
2047 exprNode_loc (fexp)))
2049 sRef_showStateInfo (fref);
2050 sRef_setAllocated (fref, exprNode_loc (fexp));
2053 else if (sRef_isPossiblyDead (fref))
2056 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
2057 message ("Possibly dead storage %qpassed as special parameter to %s: %s",
2058 sRef_unparseOpt (fref),
2059 exprNode_unparse (fcn),
2060 exprNode_unparse (fexp)),
2061 exprNode_loc (fexp)))
2063 sRef_showStateInfo (fref);
2064 sRef_setAllocated (fref, exprNode_loc (fexp));
2072 if (uentry_hasStateClauseList (ue))
2074 checkPassstateClauseList (ue, fexp, fref, argno);
2079 else if (sRef_isStateDefined (tref))
2081 exprNode_checkUseParam (fexp);
2085 if (isSpec || (!context_getFlag (FLG_IMPOUTS)))
2087 exprNode_checkUseParam (fexp);
2091 if (!sRef_isMacroParamRef (fref)
2092 && (ctype_isRealAP (ct)))
2094 if (sRef_isAddress (fref))
2096 if (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref))
2101 ("Unallocated address %qpassed as implicit "
2102 "out parameter: %s",
2103 sRef_unparseOpt (fref),
2104 exprNode_unparse (fexp)),
2105 exprNode_loc (fexp));
2106 sRef_setAllocated (fref, exprNode_loc (fexp));
2110 /* yes, I really mean this! */
2111 tref = sRef_copy (tref);
2112 sRef_setAllocated (tref, exprNode_loc (fexp));
2119 exprNode_checkUseParam (fexp);
2124 if (sRef_isNew (fref))
2126 alkind tkind = sRef_getAliasKind (tref);
2128 if ((sRef_isFresh (fref) || sRef_isOnly (fref))
2129 && !alkind_isOnly (tkind)
2130 && !alkind_isKeep (tkind)
2131 && !alkind_isOwned (tkind)
2132 && !alkind_isError (tkind)
2133 && !uentry_isReturned (arg))
2138 message ("New fresh storage %q(type %s) passed as %s (not released): %s",
2139 sRef_unparseOpt (fref),
2140 ctype_unparse (sRef_getType (fref)),
2141 alkind_unparse (sRef_getAliasKind (tref)),
2142 exprNode_unparse (fexp)),
2143 exprNode_loc (fexp));
2144 DPRINTF (("Fresh: %s", sRef_unparseFull (fref)));
2148 if (sRef_isNewRef (fref) && !sRef_isKillRef (tref))
2150 alkind ak = sRef_getAliasKind (tref);
2152 if (!alkind_isError (ak))
2156 message ("New reference %q(type %s) passed as %s (not released): %s",
2157 sRef_unparseOpt (fref),
2158 ctype_unparse (sRef_getType (fref)),
2159 alkind_unparse (sRef_getAliasKind (tref)),
2160 exprNode_unparse (fexp)),
2161 exprNode_loc (fexp));
2167 (void) checkTransfer (fexp, exprNode_getSref (fexp),
2168 exprNode_undefined, tref,
2170 exprNode_loc (fexp), TT_FCNPASS);
2173 fref = exprNode_getSref (fexp);
2175 if (isOut && !sRef_isDead (fref) && !sRef_isPossiblyDead (fref))
2179 if (ctype_isRealAP (sRef_getType (fref)))
2181 base = sRef_makePointer (fref);
2190 exprNode_checkMSet (fexp, base);
2194 exprNode_checkSet (fexp, base);
2197 if (sRef_isValid (base))
2201 sRef_clearDerived (base);
2202 sRef_setDefined (base, exprNode_loc (fexp));
2203 usymtab_clearAlias (base);
2204 sRef_setNullUnknown (base, exprNode_loc (fexp));
2210 if (sRef_isValid (fref))
2212 sRef_setPartial (fref, exprNode_loc (fexp));
2216 atFunction = exprNode_undefined;
2220 /* need to fixup here: derived refs could be bogus */
2221 /* (better to change sRef to not add derivs for "protected" ref) */
2223 uentry_fixupSref (arg);
2227 DPRINTF (("Check pass: ==> %s",
2228 sRef_unparseFull (fref)));
2232 checkGlobReturn (uentry glob)
2234 sRef_protectDerivs ();
2235 checkGlobTrans (glob, TT_GLOBRETURN);
2236 sRef_clearProtectDerivs ();
2239 void checkParamReturn (uentry actual)
2241 checkLeaveTrans (actual, TT_PARAMRETURN);
2244 void checkLoseRef (uentry actual)
2246 checkLeaveTrans (actual, TT_LEAVETRANS);
2250 checkLeaveTrans (uentry actual, transferKind transferType)
2252 sRef aref = uentry_getSref (actual);
2253 sRef origref = uentry_getOrigSref (actual);
2255 if (transferType == TT_PARAMRETURN
2256 && (sRef_isKeep (origref) || sRef_isOnly (origref)
2257 || sRef_isOwned (origref)))
2259 /* caller cannot use, nothing to check */
2263 if (sRef_isNSLocalVar (origref))
2269 DPRINTF (("Leave trans: %s", uentry_unparseFull (actual)));
2271 (void) checkCompletelyDefined (exprNode_undefined, aref, aref,
2272 exprNode_undefined, origref,
2274 g_currentloc, transferType,
2281 checkGlobTrans (uentry glob, transferKind type)
2283 sRef eref = uentry_getOrigSref (glob);
2285 (void) checkCompletelyDefined (exprNode_undefined, uentry_getSref (glob), uentry_getSref (glob),
2286 exprNode_undefined, eref,
2288 g_currentloc, type, 0, TRUE);
2292 ** For lhs of assignment, alias kind is set from basic type.
2297 fixAssignLhs (sRef s)
2299 sRef_resetStateComplete (s);
2302 static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srhs,
2306 ctype st = ctype_realType (sRef_getType (srhs));
2308 if (ctype_isSU (st) && ctype_isRealSU (sRef_getType (slhs))
2309 && ctype_match (sRef_getType (slhs), st))
2311 if (tt == TT_DOASSIGN && sRef_isStateDefined (srhs))
2313 sRef_setDefinedComplete (slhs, loc);
2316 if (sRef_isDependent (slhs)
2317 || sRef_isObserver (slhs)
2318 || sRef_isExposed (slhs))
2324 if (sRef_isLocalVar (slhs)
2325 && sRef_isFileOrGlobalScope (sRef_getRootBase (srhs)))
2327 sRef_setDependent (slhs, exprNode_loc (lhs));
2331 if (ctype_isUnion (st))
2333 sRef_setDefState (slhs, sRef_getDefState (srhs),
2334 exprNode_loc (lhs));
2336 sRefSet_realElements (sRef_derivedFields (srhs), sr)
2338 if (sRef_isField (sr))
2340 cstring fieldname = sRef_getField (sr);
2341 sRef lfld = sRef_makeField (slhs, fieldname);
2343 (void) checkTransfer (rhs, sr, lhs, lfld,
2345 exprNode_loc (lhs), tt);
2347 } end_sRefSet_realElements ;
2351 uentryList fields = ctype_getFields (st);
2353 uentryList_elements (fields, field)
2355 sRef rfld = sRef_makeField (srhs, uentry_rawName (field));
2356 sRef lfld = sRef_makeField (slhs, uentry_rawName (field));
2357 (void) checkTransfer (rhs, rfld, lhs, lfld,
2359 exprNode_loc (lhs), tt);
2360 } end_uentryList_elements ;
2363 if (sRef_isOnly (srhs))
2365 sRef_setKeptComplete (srhs, loc);
2373 checkInitTransfer (exprNode lhs, exprNode rhs)
2375 sRef slhs = exprNode_getSref (lhs);
2377 if (sRef_isFileOrGlobalScope (slhs) || (!sRef_isCvar (slhs)))
2379 (void) checkTransfer (rhs, exprNode_getSref (rhs),
2382 exprNode_loc (rhs), TT_GLOBINIT);
2386 checkAssignTransfer (lhs, rhs);
2391 checkAssignTransfer (exprNode lhs, exprNode rhs)
2393 sRef slhs = exprNode_getSref (lhs);
2394 sRef srhs = exprNode_getSref (rhs);
2395 sRef base = sRef_getBaseSafe (slhs);
2398 DPRINTF (("Check assign: %s = %s", exprNode_unparse (lhs),
2399 exprNode_unparse (rhs)));
2400 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2401 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2403 if (ctype_isRealSU (sRef_getType (srhs)))
2405 checkStructTransfer (lhs, slhs, rhs, srhs, exprNode_loc (lhs), TT_FIELDASSIGN);
2409 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2410 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2411 (void) checkTransfer (rhs, srhs, lhs, slhs,
2413 exprNode_loc (lhs), TT_DOASSIGN);
2414 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2415 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2418 if (sRef_isConst (srhs) && sRef_isLocalState (srhs))
2420 /* constants can match anything (e.g., NULL) */
2421 sRef_setAliasKind (slhs, AK_ERROR, fileloc_undefined);
2424 if (sRef_isValid (base) && sRef_isStateDefined (base))
2426 sRef_setPdefined (base, g_currentloc);
2429 if (sRef_isPartial (srhs))
2431 sRef_setPartial (slhs, exprNode_loc (rhs));
2434 ns = sRef_getNullState (srhs);
2436 if (nstate_possiblyNull (ns))
2438 if (usymtab_isGuarded (srhs))
2444 sRef_setNullStateInnerComplete (slhs, ns, exprNode_loc (rhs));
2446 if (sRef_isExposed (srhs) || sRef_isObserver (srhs))
2448 sRef_setExKind (slhs, sRef_getExKind (srhs), exprNode_loc (rhs));
2451 DPRINTF (("Done transfer: %s", sRef_unparseFull (slhs)));
2455 checkTransferNullAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2456 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2457 fileloc loc, transferKind transferType)
2459 alkind tkind = sRef_getAliasKind (tref);
2460 ctype ttyp = ctype_realType (sRef_getType (tref));
2462 if (ctype_isUnknown (ttyp))
2464 ttyp = exprNode_getType (texp);
2466 if (ctype_isUnknown (ttyp))
2468 ttyp = exprNode_getType (fexp);
2470 if (ctype_isUnknown (ttyp))
2472 ttyp = sRef_getType (fref);
2477 if (ctype_isFunction (ttyp) && (transferType == TT_FCNRETURN))
2479 ttyp = ctype_getReturnType (ttyp);
2483 ** check for null (don't need to check aliases??)
2486 if (sRef_possiblyNull (fref)
2487 && !usymtab_isGuarded (fref)
2488 && ctype_isRealAP (ttyp))
2490 if (!alkind_isLocal (tkind) && !alkind_isFresh (tkind)
2491 && !sRef_perhapsNull (tref)
2492 && !(transferType == TT_DOASSIGN))
2494 if (transferType == TT_GLOBINIT)
2496 if (sRef_isNotNull (tref))
2499 (FLG_SYNTAX, /*@i432 kuldge flag... */
2500 message ("%s %q initialized to %s value: %q",
2501 sRef_getScopeName (tref),
2502 sRef_unparse (tref),
2503 sRef_nullMessage (fref),
2504 generateText (fexp, texp, tref, transferType)),
2507 sRef_showNullInfo (fref);
2508 sRef_setNullError (tref);
2515 message ("%s %q initialized to %s value: %q",
2516 sRef_getScopeName (tref),
2517 sRef_unparse (tref),
2518 sRef_nullMessage (fref),
2519 generateText (fexp, texp, tref, transferType)),
2522 sRef_showNullInfo (fref);
2523 sRef_setNullError (tref);
2530 ((transferType == TT_FCNPASS) ? FLG_NULLPASS : FLG_NULLRET,
2531 message ("%q storage %q%s: %q",
2532 cstring_capitalize (sRef_nullMessage (fref)),
2533 sRef_unparseOpt (fref),
2534 transferNullMessage (transferType),
2535 generateText (fexp, texp, tref, transferType)),
2538 sRef_showNullInfo (fref);
2539 sRef_setNullError (fref);
2552 checkTransferAssignAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2553 /*@exposed@*/ sRef tref, exprNode texp, bool tfix,
2554 fileloc loc, transferKind transferType)
2556 alkind tkind = sRef_getAliasKind (tref);
2559 ** Assignment to same --- no errors, or state changes.
2560 ** This can happen when returned params are used.
2563 if (sRef_sameName (fref, tref))
2565 sRef_copyState (tref, fref);
2569 if ((alkind_isOnly (tkind) || alkind_isFresh (tkind)
2570 || alkind_isNewRef (tkind) || alkind_isOwned (tkind))
2571 && !(sRef_isDead (tref)
2572 || sRef_isStateUndefined (tref)
2573 || sRef_isUnuseable (tref)
2574 || sRef_isPartial (tref)
2575 || sRef_definitelyNull (tref)
2576 || sRef_isStackAllocated (tref)
2577 || sRef_isAllocIndexRef (tref))
2578 && !(sRef_same (fref, tref)) /* okay to assign to self (returned params) */
2579 && !(usymtab_isDefinitelyNull (tref)))
2581 if (context_getFlag (FLG_MUSTFREE))
2583 if (canLoseReference (tref, loc))
2589 if (sRef_hasLastReference (tref))
2593 message ("Last reference %q to %s storage %q(type %s) not released "
2594 "before assignment: %q",
2595 sRef_unparse (tref),
2596 alkind_unparse (tkind),
2597 sRef_unparseOpt (sRef_getAliasInfoRef (tref)),
2598 ctype_unparse (sRef_getType (tref)),
2599 generateText (fexp, texp, tref, transferType)),
2602 sRef_showRefLost (tref);
2607 if (context_inGlobalScope ())
2609 /* no errors for static initializations */
2614 ** don't report this error for a[i], since it could
2615 ** be a new element.
2618 if (alkind_isNewRef (tkind))
2623 ("%q %q(type %s) not released before assignment: %q",
2625 (alkind_isKillRef (sRef_getOrigAliasKind (tref))
2626 ? "Kill reference parameter" : "New reference"),
2627 sRef_unparseOpt (tref),
2628 ctype_unparse (sRef_getType (tref)),
2629 generateText (fexp, texp, tref, transferType)),
2632 sRef_showAliasInfo (tref);
2633 sRef_setAliasKind (tref, AK_ERROR, loc);
2637 (!(sRef_isUnknownArrayFetch (tref)
2638 && !context_getFlag (FLG_STRICTDESTROY))
2639 && !sRef_isUnionField (tref)
2640 && !sRef_isRelDef (tref)
2644 ("%s storage %q(type %s) not released before assignment: %q",
2645 alkind_capName (tkind),
2646 sRef_unparseOpt (tref),
2647 ctype_unparse (sRef_getType (tref)),
2648 generateText (fexp, texp, tref, transferType)),
2651 sRef_showAliasInfo (tref);
2663 fixAssignLhs (tref);
2665 if (sRef_isRefCounted (tref)) /* tkind might not be correct now */
2667 if (sRef_isNewRef (fref))
2669 sRef_setAliasKind (tref, AK_NEWREF, loc);
2671 else if (sRef_isConst (fref))
2673 /* for now, constants are not ref counted */
2674 sRef_setAliasKind (tref, AK_ERROR, loc);
2681 if (!sRef_isNSLocalVar (tref)
2682 && sRef_isRefCounted (fref)
2683 && sRef_isStateDefined (fref))
2687 message ("New reference %qto reference counted storage: %q",
2688 sRef_unparseOpt (tref),
2689 generateText (fexp, texp, tref, transferType)),
2695 ** Not for structures and unions, since assignments copy.
2698 if (sRef_isStack (fref)
2699 && !ctype_isSU (ctype_realType (sRef_getType (fref))))
2701 sRef_setAliasKindComplete (tref, AK_STACK, loc);
2704 if (sRef_isNSLocalVar (tref)
2705 && !sRef_isOwned (tref) /*< should only apply to static >*/
2706 && ctype_isMutable (sRef_getType (tref)))
2708 if (sRef_isOnly (fref) && sRef_isNew (fref))
2712 sRef_setFresh (tref, loc);
2719 ** requires sRef_isOnly (fref)
2723 checkOnlyTransferAux (sRef fref, exprNode fexp, bool ffix,
2724 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2725 fileloc loc, transferKind transferType)
2727 alkind tkind = sRef_getAliasKind (tref);
2729 if (sRef_isExposed (tref) || sRef_isObserver (tref))
2731 if (transferType == TT_FCNRETURN && sRef_isNew (fref)
2732 && !alkind_isError (tkind))
2736 message ("Only storage %q%q (will not be released): %q",
2737 sRef_unparseOpt (fref),
2738 transferErrorMessage (transferType, tkind),
2739 generateText (fexp, texp, tref, transferType)),
2742 sRef_showAliasInfo (fref);
2746 /* no errors for exposed transfers (is this good enough?) */
2748 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind) || alkind_isOwned (tkind))
2752 else if ((transferType == TT_FCNPASS)
2753 && (alkind_isUnknown (tkind)
2754 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2756 if (sRef_isFresh (fref)
2757 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2759 if (!ffix) sRef_setAliasKind (fref, AK_UNKNOWN, loc);
2762 else if (alkind_isLocal (tkind)
2763 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2765 if ((transferType == TT_DOASSIGN)
2766 && sRef_isNew (fref)
2767 && sRef_isOnly (fref))
2771 if (alkind_isUnknown (tkind)
2772 && sRef_isFileOrGlobalScope (sRef_getRootBase (tref)))
2775 (FLG_ONLYUNQGLOBALTRANS,
2776 message ("Only storage %q%q: %q",
2777 sRef_unparseOpt (fref),
2778 transferErrorMessage (transferType, tkind),
2779 generateText (fexp, texp, tref, transferType)),
2782 sRef_showAliasInfo (fref);
2783 sRef_setAliasKind (tref, AK_ERROR, loc);
2788 if (!error && !ffix)
2790 sRef_setFresh (tref, loc);
2795 if (alkind_isLocal (tkind))
2797 if (sRef_sameName (tref, fref))
2799 ; /* don't set this --- corresponds to return transfer */
2804 ** Don't set local to dependent. Error will
2805 ** be detected through aliasing. Except for
2809 if (!tfix && sRef_isThroughArrayFetch (fref)
2810 && context_getFlag (FLG_DEPARRAYS))
2812 sRef_setDependent (tref, loc);
2820 message ("Only storage %q%q: %q",
2821 sRef_unparseOpt (fref),
2822 transferErrorMessage (transferType, tkind),
2823 generateText (fexp, texp, tref, transferType)),
2826 sRef_showAliasInfo (fref);
2833 if (alkind_isError (tkind)
2834 || (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT)))
2836 flagcode_recordSuppressed (FLG_ONLYTRANS);
2840 if ((alkind_isKept (tkind) || alkind_isStack (tkind)
2841 || alkind_isDependent (tkind))
2842 && sRef_isNSLocalVar (tref))
2850 message ("Only storage %q%q: %q",
2851 sRef_unparseOpt (fref),
2852 transferErrorMessage (transferType, tkind),
2853 generateText (fexp, texp, tref, transferType)),
2856 sRef_showAliasInfo (fref);
2858 if (transferType == TT_DOASSIGN)
2861 ** alias kind unknown to suppress future messages
2864 if (!ffix && sRef_isNSLocalVar (sRef_getRootBase (fref)))
2866 sRef_clearAliasKind (fref);
2876 ** ??? same as checkOnly ?
2880 checkOwnedTransferAux (sRef fref, exprNode fexp, bool ffix,
2881 sRef tref, exprNode texp, bool tfix,
2882 fileloc loc, transferKind transferType)
2884 alkind tkind = sRef_getAliasKind (tref);
2886 if (sRef_isExposed (tref) || sRef_isObserver (tref))
2888 if (transferType == TT_FCNRETURN && sRef_isNew (fref))
2892 message ("Owned storage %q%q (will not be released): %q",
2893 sRef_unparseOpt (fref),
2894 transferErrorMessage (transferType, tkind),
2895 generateText (fexp, texp, tref, transferType)),
2898 sRef_showAliasInfo (fref);
2902 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind)
2903 || alkind_isDependent (tkind)
2904 || alkind_isOwned (tkind))
2908 else if (alkind_isLocal (tkind)
2909 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2911 if ((transferType == TT_DOASSIGN)
2912 && sRef_isNew (fref) && sRef_isOnly (fref))
2916 sRef_setFresh (tref, loc);
2923 else if ((transferType == TT_FCNPASS)
2924 && (alkind_isUnknown (tkind)
2925 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2927 if (sRef_isFresh (fref)
2928 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2930 if (!ffix) { sRef_clearAliasKind (fref); }
2935 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2937 flagcode_recordSuppressed (FLG_OWNEDTRANS);
2941 if (alkind_isKept (tkind) && sRef_isNSLocalVar (tref))
2949 message ("Owned storage %q%q: %q",
2950 sRef_unparseOpt (fref),
2951 transferErrorMessage (transferType, tkind),
2952 generateText (fexp, texp, tref, transferType)),
2957 if (transferType == TT_DOASSIGN)
2960 ** alias kind unknown to suppress future messages
2963 if (!ffix) { sRef_clearAliasKind (fref); }
2969 checkFreshTransferAux (sRef fref, exprNode fexp, bool ffix,
2970 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2971 fileloc loc, transferKind transferType)
2973 alkind tkind = sRef_getAliasKind (tref);
2976 ** error to return fresh as non-only
2979 if (transferType == TT_FCNRETURN
2980 && !(alkind_isOnly (tkind) || alkind_isNewRef (tkind)))
2982 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2984 flagcode_recordSuppressed (FLG_NEWREFTRANS);
2988 if (alkind_isError (tkind))
2992 sRef_killComplete (fref, loc);
2995 else if (alkind_isRefCounted (tkind))
3000 ("New reference returned without newref qualifier: %q",
3001 generateText (fexp, texp, tref, transferType)),
3004 sRef_showAliasInfo (fref);
3005 sRef_killComplete (fref, loc);
3012 message ("Fresh storage %q (should be only): %q",
3013 transferErrorMessage (transferType, tkind),
3014 generateText (fexp, texp, tref, transferType)),
3017 sRef_showAliasInfo (fref);
3018 sRef_killComplete (fref, loc);
3025 ** Okay to assign fresh to only, shared or unqualified.
3027 ** should generate other errors?
3030 if (alkind_isOnly (tkind))
3032 if (transferType == TT_DOASSIGN && !sRef_isFileOrGlobalScope (tref))
3036 if (!sRef_isNSLocalVar (tref))
3038 sRef_setKeptComplete (fref, loc);
3044 if (sRef_isConst (fref))
3052 sRef_killComplete (fref, loc);
3057 else if (alkind_isOwned (tkind))
3061 sRef_setDependentComplete (fref, loc);
3064 else if (alkind_isRefCounted (tkind)
3065 && (transferType == TT_FCNRETURN) && sRef_isFresh (fref))
3069 sRef_killComplete (fref, loc);
3072 else if (alkind_isKeep (tkind))
3076 if (!sRef_isNSLocalVar (tref))
3078 sRef_setKeptComplete (fref, loc);
3082 else if (alkind_isShared (tkind))
3084 if (!ffix) { sRef_setShared (fref, loc); }
3086 else if (alkind_isLocal (tkind) || alkind_isUnknown (tkind))
3088 if (transferType == TT_DOASSIGN || transferType == TT_FCNRETURN)
3091 ** local shares fresh. Make it owned/dependent.
3096 sRef_setOwned (tref, loc);
3101 sRef_setDependentComplete (fref, loc);
3104 /* NO! sRef_clearAliasKind (fref); */
3108 if (context_getFlag (FLG_PASSUNKNOWN))
3110 sRef_clearAliasKind (fref);
3121 checkTransferExposure (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
3122 sRef tref, exprNode texp, bool tfix,
3124 transferKind transferType)
3126 alkind fkind = sRef_getAliasKind (fref);
3127 alkind tkind = sRef_getAliasKind (tref);
3128 exkind tekind = sRef_getExKind (tref);
3130 if (sRef_isObserver (fref) && ctype_isMutable (sRef_getType (fref)))
3133 ** observer -> exposed or observer
3137 ** observer -> temp is okay [NO! really? only in function calls]
3140 if (sRef_isExposed (tref) || sRef_isObserver (tref)
3141 || alkind_isLocal (tkind))
3145 if ((transferType == TT_DOASSIGN) && alkind_isLocal (tkind))
3149 sRef_setAliasKindComplete (tref, fkind, loc);
3155 if (transferType == TT_FCNRETURN
3156 || transferType == TT_DOASSIGN
3157 || transferType == TT_FIELDASSIGN
3158 || transferType == TT_GLOBINIT)
3160 bool hasError = FALSE;
3162 if (exprNode_isStringLiteral (fexp)
3163 && transferType == TT_GLOBINIT)
3165 hasError = optgenerror
3167 message ("Read-only string literal storage %q%q: %q",
3168 sRef_unparseOpt (fref),
3169 transferErrorExpMessage (transferType, tekind),
3170 generateText (fexp, texp, tref, transferType)),
3173 sRef_setAliasKind (fref, AK_ERROR, fileloc_undefined);
3177 if ((transferType == TT_DOASSIGN
3178 || transferType == TT_FIELDASSIGN)
3179 && (sRef_isNSLocalVar (tref)
3180 || (exprNode_isStringLiteral (fexp)
3181 && ctype_isRealArray (exprNode_getType (texp)))))
3183 ; /* No error for local assignment or assignment
3184 to static array (copies string). */
3188 if (exprNode_isStringLiteral (fexp))
3190 hasError = optgenerror
3193 ("Read-only string literal storage %q%q: %q",
3194 sRef_unparseOpt (fref),
3195 transferErrorExpMessage (transferType, tekind),
3196 generateText (fexp, texp, tref, transferType)),
3203 hasError = optgenerror
3206 ("Observer storage %q%q: %q",
3207 sRef_unparseOpt (fref),
3208 transferErrorExpMessage (transferType, tekind),
3209 generateText (fexp, texp, tref, transferType)),
3217 if (transferType != TT_GLOBINIT)
3219 sRef_showExpInfo (fref);
3220 sRef_setAliasKind (tref, AK_ERROR, loc);
3225 if (transferType == TT_DOASSIGN && !tfix)
3227 DPRINTF (("Setting unknown!"));
3228 /* sRef_setAliasKind (tref, AK_ERROR, loc); */
3232 else /* TT_FCNPASS */
3234 llassert (transferType == TT_FCNPASS);
3236 if (alkind_isTemp (tkind)
3237 || alkind_isDependent (tkind)
3238 || alkind_isRefCounted (tkind))
3244 if (!alkind_isError (tkind))
3248 message ("Observer storage %q%q: %q",
3249 sRef_unparseOpt (fref),
3250 transferErrorMessage (transferType, tkind),
3251 generateText (fexp, texp, tref, transferType)),
3254 sRef_showExpInfo (fref);
3255 sRef_clearAliasState (fref, loc);
3262 else if (sRef_isExposed (fref) && ctype_isMutable (sRef_getType (fref)))
3264 if (transferType == TT_FCNRETURN)
3266 if (!(sRef_isExposed (tref) || sRef_isObserver (tref)
3267 || sRef_isParam (fref)))
3271 message ("Exposed storage %q%q: %q",
3272 sRef_unparseOpt (fref),
3273 transferErrorExpMessage (transferType, tekind),
3274 generateText (fexp, texp, tref, transferType)),
3277 sRef_showExpInfo (fref);
3281 else if (transferType == TT_FCNPASS)
3283 if (!(sRef_isExposed (tref)
3284 || sRef_isObserver (tref)
3285 || (alkind_isUnknown (tkind)
3286 || alkind_isDependent (tkind)
3287 || alkind_isTemp (tkind)
3288 || alkind_isKillRef (tkind)
3289 || alkind_isRefCounted (tkind))))
3291 if (alkind_isUnique (tkind) || alkind_isError (tkind))
3298 message ("Exposed storage %q%q: %q",
3299 sRef_unparseOpt (fref),
3300 transferErrorMessage (transferType, tkind),
3301 generateText (fexp, texp, tref, transferType)),
3304 sRef_showExpInfo (fref);
3305 sRef_clearAliasState (fref, loc);
3315 else if (transferType == TT_DOASSIGN
3316 /* evans 2001-10-05: added TT_FIELDASSIGN: */
3317 || transferType == TT_FIELDASSIGN)
3319 if (!(sRef_isExposed (tref)
3320 || !sRef_isCvar (tref)
3321 || (alkind_isUnknown (tkind)
3322 || alkind_isDependent (tkind)
3323 || alkind_isRefCounted (tkind)
3324 || alkind_isNewRef (tkind)
3325 || alkind_isFresh (tkind)
3326 || alkind_isLocal (tkind))))
3330 message ("Exposed storage %q%q: %q",
3331 sRef_unparseOpt (fref),
3332 transferErrorExpMessage (transferType, tekind),
3333 generateText (fexp, texp, tref, transferType)),
3336 sRef_showExpInfo (fref);
3339 if (!tfix) { sRef_setExposed (tref, loc); }
3343 llassert (transferType == TT_GLOBPASS
3344 || transferType == TT_GLOBRETURN
3345 || transferType == TT_PARAMRETURN
3346 || transferType == TT_LEAVETRANS
3347 || transferType == TT_GLOBINIT);
3357 ** returns TRUE if there is no error reported
3359 ** if fixt, don't change tref (except if error reported.)
3360 ** if fixf, don't change fref (except if error reported.)
3364 checkTransferAux (exprNode fexp, /*@exposed@*/ sRef fref, bool ffix,
3365 exprNode texp, /*@exposed@*/ sRef tref, bool tfix,
3366 fileloc loc, transferKind transferType)
3370 bool isassign = (transferType == TT_DOASSIGN);
3371 bool isfieldassign = (transferType == TT_FIELDASSIGN);
3372 bool iseitherassign = isassign || (transferType == TT_FIELDASSIGN);
3373 bool isfcnpass = (transferType == TT_FCNPASS);
3374 bool isfcnreturn = (transferType == TT_FCNRETURN);
3381 checkTransferNullAux (fref, fexp, ffix, tref, texp, tfix,
3388 checkTransferAssignAux (fref, fexp, ffix, tref, texp, tfix,
3393 ** Check for definition
3397 ** errors passing out params already detected in checkAnyCall
3405 || (!sRef_isNSLocalVar (tref)
3406 && (sRef_isAnyDefined (tref) || !sRef_stateKnown (tref))))
3410 if (!ynm_toBoolRelaxed
3411 (checkCompletelyDefined (fexp, fref, fref,
3414 loc, transferType, 0, TRUE)))
3422 if (defok && iseitherassign)
3424 sRef_setDefState (tref, sRef_getDefState (fref), loc);
3433 checkTransferExposure (fref, fexp, ffix, tref, texp, tfix,
3436 fkind = sRef_getAliasKind (fref);
3437 tkind = sRef_getAliasKind (tref);
3443 if (alkind_isOnly (fkind))
3446 checkOnlyTransferAux (fref, fexp, ffix,
3450 else if (alkind_isFresh (fkind))
3453 checkFreshTransferAux (fref, fexp, ffix,
3457 else if (alkind_isOwned (fkind))
3460 checkOwnedTransferAux (fref, fexp, ffix,
3464 else if (alkind_isDependent (fkind))
3468 (sRef_isExposed (tref) || sRef_isObserver (tref)))
3472 else if ((alkind_isOnly (tkind) || alkind_isKeep (tkind)
3473 || alkind_isOwned (tkind))
3474 || (!isfcnpass && alkind_isTemp (tkind)))
3478 if (sRef_isLocalVar (fref))
3480 sRef depRef = dependentReference (fref);
3482 if (sRef_isValid (depRef) && sRef_isLocalVar (depRef))
3485 sRef_kill (depRef, loc);
3486 sRef_kill (fref, loc);
3496 if (canLoseLocalReference (fref, loc))
3504 (FLG_DEPENDENTTRANS,
3505 message ("%s storage %q%q: %q",
3506 alkind_capName (fkind),
3507 sRef_unparseOpt (fref),
3508 transferErrorMessage (transferType, tkind),
3509 generateText (fexp, texp, tref, transferType)),
3512 DPRINTF (("Here: %s / %s",
3513 sRef_unparseFull (fref),
3514 sRef_unparseFull (tref)));
3516 sRef_showAliasInfo (fref);
3522 if (isassign && (alkind_isFresh (tkind) || alkind_isLocal (tkind)))
3526 sRef_setDependent (tref, loc);
3531 else if (alkind_isShared (fkind))
3538 if (alkind_isOnly (tkind)
3540 && (!(sRef_isObserver (tref) || sRef_isExposed (tref))
3541 && alkind_isTemp (tkind))))
3545 message ("%s storage %q%q: %q",
3546 alkind_capName (fkind),
3547 sRef_unparseOpt (fref),
3548 transferErrorMessage (transferType, tkind),
3549 generateText (fexp, texp, tref, transferType)),
3552 sRef_showAliasInfo (fref);
3557 if (alkind_isFresh (tkind) || alkind_isLocal (tkind))
3559 sRef_setShared (tref, loc);
3563 else if (alkind_isKeep (fkind))
3567 if (alkind_isKeep (tkind)
3568 || alkind_isLocal (tkind)
3569 || (isfcnreturn && sRef_isExposed (tref))
3571 && (alkind_isOnly (tkind) || alkind_isOwned (tkind))))
3573 sRef_setKept (fref, loc);
3576 && (alkind_isTemp (tkind) || alkind_isOwned (tkind)))
3582 if (!alkind_isError (tkind))
3586 message ("%s storage %q: %q",
3587 alkind_capName (fkind),
3588 transferErrorMessage (transferType, tkind),
3589 generateText (fexp, texp, tref, transferType)),
3592 sRef_showAliasInfo (fref);
3597 else if (alkind_isTemp (fkind) || alkind_isKept (fkind))
3603 if (alkind_isOnly (tkind)
3604 || alkind_isShared (tkind)
3605 || (alkind_isTemp (fkind)
3606 && !isfcnreturn && alkind_isDependent (tkind))
3607 || alkind_isOwned (tkind)
3608 || alkind_isKeep (tkind))
3610 if (!exprNode_isNullValue (fexp)
3611 && (ctype_isMutable (exprNode_getType (fexp))
3612 || (ctype_isArray (exprNode_getType (fexp))
3613 && sRef_isParam (fref)))
3614 && (!iseitherassign || sRef_isReference (tref)))
3616 if (sRef_isThroughArrayFetch (fref))
3619 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3620 FLG_STRICTUSERELEASED,
3621 message ("%s storage %q%q: %q",
3622 alkind_capName (fkind),
3623 sRef_unparseOpt (fref),
3624 transferErrorMessage (transferType, tkind),
3625 generateText (fexp, texp, tref, transferType)),
3628 sRef_showAliasInfo (fref);
3634 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3635 message ("%s storage %q%q: %q",
3636 alkind_capName (fkind),
3637 sRef_unparseOpt (fref),
3638 transferErrorMessage (transferType, tkind),
3639 generateText (fexp, texp, tref, transferType)),
3642 sRef_showAliasInfo (fref);
3648 else if (alkind_isRefCounted (fkind) || alkind_isKillRef (fkind))
3650 if (alkind_isNewRef (tkind))
3653 ** check that the refs field has been modified
3656 if (!sRef_isConst (fref))
3660 message ("Reference counted storage returned without modifying "
3661 "reference count: %s",
3662 exprNode_unparse (fexp)),
3666 else if (iseitherassign)
3668 if (alkind_isRefCounted (fkind))
3670 if (!sRef_isLocalVar (tref))
3675 ("Assignment to non-local from reference counted storage: %s",
3676 exprNode_unparse (fexp)),
3678 ("Reference counted storage should call a function returning "
3679 "a newref instead of direct assignments."),
3690 if (alkind_isRefCounted (tkind) || alkind_isTemp (tkind))
3692 /* okay --- no change in state */
3694 else if (alkind_isKillRef (tkind))
3696 if (!ffix && !tfix && !(transferType == TT_FCNRETURN))
3698 sRef_killComplete (fref, loc);
3703 if (!alkind_isError (tkind))
3707 message ("Reference counted storage %q: %q",
3708 transferErrorMessage (transferType, tkind),
3709 generateText (fexp, texp, tref, transferType)),
3722 if (alkind_isOnly (tkind) || alkind_isKeep (tkind))
3724 if (sRef_isAddress (fref))
3727 (FLG_IMMEDIATETRANS,
3728 message ("Immediate address %q %q: %q",
3729 sRef_unparse (fref),
3730 transferErrorMessage (transferType, tkind),
3731 generateText (fexp, texp, tref, transferType)),
3734 sRef_setAliasKind (fref, AK_ERROR, loc);
3738 if ((alkind_isUnknown (fkind) || alkind_isStatic (fkind))
3739 && !sRef_isDefinitelyNull (fref)
3741 && (!exprNode_isNullValue (fexp)))
3743 flagcode errkind = alkind_isStatic (fkind)
3744 ? FLG_STATICTRANS : FLG_UNKNOWNTRANS;
3746 if (transferType == TT_GLOBINIT)
3748 if (errkind == FLG_STATICTRANS)
3750 errkind = FLG_STATICINITTRANS;
3754 errkind = FLG_UNKNOWNINITTRANS;
3760 message ("%s storage %s %q: %q",
3761 alkind_capName (fkind),
3762 exprNode_unparse (fexp),
3763 transferErrorMessage (transferType, tkind),
3764 generateText (fexp, texp, tref, transferType)),
3767 sRef_showAliasInfo (fref);
3772 /* don't kill shared to suppress future messages */
3773 if (!alkind_isShared (fkind))
3779 /*< yuk! should do this in aliasaux >*/
3781 if (!sRef_isNSLocalVar (tref) && !sRef_sameName (fref, tref))
3785 sRef_setKeptComplete (fref, loc);
3789 sRef_setKept (fref, loc);
3800 if (alkind_isKeep (tkind))
3802 sRef_setKeptComplete (fref, loc);
3806 sRef_killComplete (fref, loc);
3811 if (alkind_isKeep (tkind))
3813 sRef_setKept (fref, loc);
3817 sRef_kill (fref, loc);
3824 else if (alkind_isOwned (tkind))
3826 /* don't kill shared to suppress future messages */
3827 if (!alkind_isShared (fkind))
3830 || !sRef_sameName (fref, tref)) /* result of return parameter */
3836 sRef_setDependentComplete (fref, loc);
3840 sRef_setDependent (fref, loc);
3846 else if (alkind_isShared (tkind))
3848 if (alkind_isFresh (fkind) || alkind_isLocal (fkind))
3852 sRef_setShared (fref, loc);
3856 else if (alkind_isUnknown (tkind) && context_getFlag (FLG_MEMIMPLICIT))
3858 if (alkind_isDependent (fkind))
3860 if (!exprNode_isNullValue (fexp)
3861 && ctype_isMutable (exprNode_getType (fexp))
3862 && (!iseitherassign || sRef_isReference (tref)))
3864 if (canLoseReference (fref, loc))
3871 (FLG_DEPENDENTTRANS,
3872 message ("%s storage %q%q: %q",
3873 alkind_capName (fkind),
3874 sRef_unparseOpt (fref),
3875 transferErrorMessage (transferType, tkind),
3876 generateText (fexp, texp, tref, transferType)),
3879 DPRINTF (("Here: %s / %s", sRef_unparseFull (fref),
3880 sRef_unparseFull (tref)));
3881 sRef_showAliasInfo (fref);
3887 else if (alkind_isNewRef (tkind))
3891 sRef_killComplete (fref, loc);
3894 else if (alkind_isKillRef (tkind))
3896 if (transferType == TT_FCNRETURN)
3898 if (sRef_isNewRef (fref))
3902 message ("New reference returned as temp reference: %q",
3903 generateText (fexp, texp, tref, transferType)),
3906 sRef_showAliasInfo (fref);
3912 if (sRef_isNewRef (fref))
3914 sRef_killComplete (fref, loc);
3918 if (sRef_isRefCounted (fref)
3919 && sRef_isCvar (fref)
3920 && !sRef_isLocalVar (fref))
3925 ("External reference counted storage released: %q",
3926 generateText (fexp, texp, tref, transferType)),
3929 sRef_showAliasInfo (fref);
3945 checkMetaStateConsistent (/*@exposed@*/ sRef fref, sRef tref,
3946 fileloc loc, /*@unused@*/ transferKind transferType)
3949 ** Checks if it is consistent to leave storage marked as tref in state of fref.
3952 valueTable fvalues = sRef_getValueTable (fref);
3953 valueTable tvalues = sRef_getValueTable (tref);
3955 DPRINTF (("Metastate consistent: %s => %s",
3956 sRef_unparseFull (fref),
3957 sRef_unparseFull (tref)));
3959 if (valueTable_isUndefined (tvalues) || valueTable_isUndefined (fvalues)) {
3960 /* Cannot check without value tables. An error was already detected. */
3961 DPRINTF (("No value table: %s / %s",
3962 bool_unparse (valueTable_isUndefined (tvalues)),
3963 bool_unparse (valueTable_isUndefined (fvalues))));
3967 valueTable_elements (fvalues, fkey, fval) {
3969 metaStateInfo minfo;
3971 DPRINTF (("Transfer: %s", fkey));
3972 tval = valueTable_lookup (tvalues, fkey);
3973 minfo = context_lookupMetaStateInfo (fkey);
3975 if (!stateValue_isDefined (tval))
3977 if (ctype_isUnknown (sRef_getType (fref)))
3979 ; /* Okay, put in default values without knowing type */
3984 DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
3985 sRef_unparseFull (tref),
3991 llassert (metaStateInfo_isDefined (minfo));
3993 if (stateValue_isError (fval) || stateValue_isError (tval))
3997 else if (sRef_isDefinitelyNull (fref)
3998 || usymtab_isDefinitelyNull (fref))
4000 ; /* No errors for null values in state transfers. */
4005 stateCombinationTable sctable = metaStateInfo_getTransferTable (minfo);
4006 cstring msg = cstring_undefined;
4007 int nval = stateCombinationTable_lookup (sctable,
4008 stateValue_getValue (fval),
4009 stateValue_getValue (tval),
4012 if (nval == stateValue_error)
4014 if (transferType == TT_LEAVETRANS)
4018 else if (transferType == TT_GLOBRETURN)
4023 ("Function returns with global %q in inconsistent state (%q is %q, should be %q)%q",
4024 sRef_unparse (sRef_getRootBase (fref)),
4025 sRef_unparse (fref),
4026 stateValue_unparseValue (fval, minfo),
4027 stateValue_unparseValue (tval, minfo),
4028 cstring_isDefined (msg)
4029 ? message (": %s", msg) : cstring_undefined),
4032 sRef_showMetaStateInfo (fref, fkey);
4035 else if (transferType == TT_GLOBPASS)
4040 ("Function called with global %q in inconsistent state (%q is %q, should be %q)%q",
4041 sRef_unparse (sRef_getRootBase (fref)),
4042 stateValue_unparseValue (fval, minfo),
4043 sRef_unparse (fref),
4044 stateValue_unparseValue (tval, minfo),
4045 cstring_isDefined (msg)
4046 ? message (": %s", msg) : cstring_undefined),
4049 sRef_showMetaStateInfo (fref, fkey);
4052 else if (transferType == TT_PARAMRETURN)
4057 ("Function returns with parameter %q in inconsistent state (%q is %q, should be %q)%q",
4058 sRef_unparse (sRef_getRootBase (fref)),
4059 sRef_unparse (fref),
4060 stateValue_unparseValue (fval, minfo),
4061 stateValue_unparseValue (tval, minfo),
4062 cstring_isDefined (msg)
4063 ? message (": %s", msg) : cstring_undefined),
4066 sRef_showMetaStateInfo (fref, fkey);
4074 ("Invalid transfer from %q %x to %q (%q)%q",
4075 stateValue_unparseValue (fval, minfo),
4076 sRef_unparse (fref),
4077 stateValue_unparseValue (tval, minfo),
4078 sRef_unparse (tref),
4079 cstring_isDefined (msg)
4080 ? message (": %s", msg) : cstring_undefined),
4083 sRef_showMetaStateInfo (fref, fkey);
4089 if (stateValue_getValue (fval) != nval)
4091 stateValue_updateValueLoc (fval, nval, loc);
4096 DPRINTF (("Transfer: %s %s -> %s",
4097 fkey, stateValue_unparse (fval), stateValue_unparse (tval)));
4098 } end_valueTable_elements ;
4102 checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref,
4104 fileloc loc, transferKind /*@i32@*/ transferType)
4106 valueTable fvalues = sRef_getValueTable (fref);
4107 valueTable tvalues = sRef_getValueTable (tref);
4109 DPRINTF (("Metastate transfer: from %s", exprNode_unparse (fexp)));
4111 DPRINTF (("Metastate transfer: %s => %s",
4112 sRef_unparseFull (fref),
4113 sRef_unparseFull (tref)));
4115 if (valueTable_isUndefined (tvalues) || valueTable_isUndefined (fvalues)) {
4116 /* Cannot check without value tables. An error was already detected. */
4117 DPRINTF (("No value table: %s / %s",
4118 bool_unparse (valueTable_isUndefined (tvalues)),
4119 bool_unparse (valueTable_isUndefined (fvalues))));
4123 valueTable_elements (fvalues, fkey, fval) {
4125 metaStateInfo minfo;
4126 stateCombinationTable sctable;
4130 DPRINTF (("Transfer: %s", fkey));
4131 tval = valueTable_lookup (tvalues, fkey);
4132 minfo = context_lookupMetaStateInfo (fkey);
4134 if (!stateValue_isDefined (tval))
4136 if (ctype_isUnknown (sRef_getType (fref)))
4138 ; /* Okay, put in default values without knowing type */
4143 DPRINTF (("Metastate transfer: %s => %s",
4144 exprNode_unparse (fexp), exprNode_unparse (texp)));
4145 DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
4146 sRef_unparseFull (tref),
4152 llassert (metaStateInfo_isDefined (minfo));
4154 if (stateValue_isError (fval))
4158 else if (stateValue_isError (tval))
4160 if (sRef_isLocalVar (tref) && transferType == TT_DOASSIGN)
4162 /* Local assignments just replace state. */
4163 stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
4164 DPRINTF (("Update: %s", stateValue_unparse (tval)));
4166 else if (transferType == TT_FCNRETURN)
4168 ; /* Returning from an unannotated function */
4172 DPRINTF (("Transfer to error: %s / %s", sRef_unparseFull (tref),
4173 transferType_unparse (transferType)));
4178 DPRINTF (("Check: %s / %s / %s / %s", fkey,
4179 metaStateInfo_unparse (minfo),
4180 stateValue_unparse (fval),
4181 stateValue_unparse (tval)));
4183 sctable = metaStateInfo_getTransferTable (minfo);
4184 msg = cstring_undefined;
4186 nval = stateCombinationTable_lookup (sctable,
4187 stateValue_getValue (fval),
4188 stateValue_getValue (tval),
4191 if (transferType == TT_DOASSIGN && sRef_isLocalVar (tref))
4193 /* Local assignments just replace state. */
4194 DPRINTF (("No transfer error assigning to local: %s", msg));
4195 stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
4196 DPRINTF (("Update: %s", stateValue_unparse (tval)));
4200 if (nval == stateValue_error)
4202 /*@i32 print extra info for assignments@*/
4207 ("Invalid transfer from %q %x to %q%q: %q",
4208 stateValue_unparseValue (fval, minfo),
4209 sRef_unparse (fref),
4210 stateValue_unparseValue (tval, minfo),
4211 cstring_isDefined (msg)
4212 ? message (" (%s)", msg) : cstring_undefined,
4213 transferErrorExcerpt (transferType, fexp, texp, fcn)),
4216 sRef_showMetaStateInfo (fref, fkey);
4217 sRef_showMetaStateInfo (tref, fkey);
4221 DPRINTF (("Suppressed transfer error: %s", msg));
4226 if (transferType == TT_FCNRETURN)
4229 ** Returning this reference from a function, mark this reference
4230 ** so no lost reference errors are returned.
4233 stateValue_updateValueLoc (fval, stateValue_error, loc);
4235 else if (stateValue_getValue (fval) != nval)
4237 stateValue_updateValueLoc (fval, nval, loc);
4248 DPRINTF (("Transfer: %s %s -> %s",
4249 fkey, stateValue_unparse (fval), stateValue_unparse (tval)));
4250 } end_valueTable_elements ;
4254 ** assigns fexp := tref or passes fexp as a parameter, or returns fexp.
4256 ** For assignments, sets alias and definition state accordingly.
4260 checkTransfer (exprNode fexp, /*@dependent@*/ sRef fref,
4261 exprNode texp, /*@dependent@*/ sRef tref,
4263 fileloc loc, transferKind transferType)
4267 if (context_inProtectVars ())
4272 DPRINTF (("Check transfer: %s => %s",
4273 sRef_unparse (fref),
4274 sRef_unparse (tref)));
4275 DPRINTF (("Check transfer: %s => %s",
4276 exprNode_unparse (fexp),
4277 exprNode_unparse (texp)));
4279 checkMetaStateTransfer (fexp, fref, texp, tref, fcn,
4283 ** for local references, we need to check
4284 ** the transfer for all possible aliases.
4287 if (sRef_isLocalVar (tref) && transferType != TT_DOASSIGN)
4289 sRefSet alias = usymtab_allAliases (tref);
4291 sRefSet_realElements (alias, atref)
4293 sRef abase = sRef_getRootBase (atref);
4295 if (sRef_isKnown (atref)
4296 && !sRef_isLocalVar (abase)
4297 && !sRef_isExternal (abase))
4299 atref = sRef_updateSref (atref);
4301 if (sRef_hasName (atref))
4303 if (!sRef_isNew (atref)
4304 && !sRef_sameName (tref, atref))
4306 context_setAliasAnnote (atref, tref);
4309 checkTransferAux (fexp, fref, TRUE,
4313 context_clearAliasAnnote ();
4316 } end_sRefSet_realElements;
4318 sRefSet_free (alias);
4321 if (sRef_isLocalVar (fref))
4323 sRefSet alias = usymtab_allAliases (fref);
4325 sRefSet_realElements (alias, afref)
4327 sRef abase = sRef_getRootBase (afref);
4329 if (sRef_isKnown (afref)
4330 && !sRef_isLocalVar (abase)
4331 && !sRef_isExternal (abase))
4333 afref = sRef_updateSref (afref);
4335 if (sRef_hasName (afref))
4337 if (!sRef_isNew (afref)
4338 && !sRef_sameName (afref, fref))
4340 context_setAliasAnnote (afref, fref);
4343 checkTransferAux (fexp, afref, FALSE,
4347 context_clearAliasAnnote ();
4350 } end_sRefSet_realElements;
4352 sRefSet_free (alias);
4356 checkTransferAux (fexp, fref, FALSE, texp, tref, FALSE,
4361 static /*@exposed@*/ sRef
4362 dependentReference (sRef sr)
4364 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4366 DPRINTF (("Dependent reference: %s", sRef_unparse (sr)));
4367 DPRINTF (("Aliases: %s", sRefSet_unparse (ab)));
4370 ** If there is a local variable that aliases sr, then there is no
4371 ** error. Make the local an only.
4374 if (!sRefSet_isEmpty (ab))
4376 sRef res = sRef_undefined;
4378 DPRINTF (("Here we are!"));
4381 ** make one an only, others alias it
4384 sRefSet_realElements (ab, current)
4386 if (sRef_isOwned (current))
4391 } end_sRefSet_realElements;
4393 if (sRef_isInvalid (res))
4396 ** evans - 2001-03-24
4397 ** No owned element, just choose one!
4398 ** (Any reason for preference?)
4401 res = sRefSet_choose (ab);
4408 return sRef_undefined;
4411 bool canLoseReference (/*@dependent@*/ sRef sr, fileloc loc)
4413 bool gotone = FALSE;
4414 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4417 ** if there is a local variable that aliases sr, then there is no
4418 ** error. Make the local an only.
4421 if (!sRefSet_isEmpty (ab))
4424 ** make one an only, others alias it
4427 sRefSet_realElements (ab, current)
4429 sRef_setLastReference (current, sr, loc);
4432 } end_sRefSet_realElements;
4440 bool canLoseLocalReference (/*@dependent@*/ sRef sr, fileloc loc)
4442 bool gotone = FALSE;
4443 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4446 ** if there is a local variable that aliases sr, then there is no
4447 ** error. Make the local an only.
4450 if (!sRefSet_isEmpty (ab))
4453 ** make one an only, others alias it
4456 sRefSet_realElements (ab, current)
4458 if (sRef_isRealLocalVar (sRef_getRootBase (current)))
4460 sRef_setLastReference (current, sr, loc);
4464 } end_sRefSet_realElements;