2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
28 # include "lclintMacros.nf"
30 # include "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 LCLint.",
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 else if (transferType == TT_DOASSIGN
1209 || transferType == TT_FIELDASSIGN
1210 || transferType == TT_GLOBINIT)
1218 message ("%s union %q has no defined field",
1219 transferType_unparse (transferType),
1220 sRef_unparse (fref)),
1227 cstringSList_free (goodFields);
1228 return ynm_fromBool (!report || isOk);
1241 ** fref is being free'd
1245 DSC_GLOB, DSC_LOCAL, DSC_PARAM, DSC_STRUCT
1248 static /*@observer@*/ cstring dscCode_unparse (dscCode desc) /*@*/
1253 return cstring_makeLiteralTemp ("killed global");
1255 return cstring_makeLiteralTemp ("variable declared in this scope");
1257 return cstring_makeLiteralTemp ("released storage");
1259 return cstring_makeLiteralTemp ("released structure parameter");
1266 checkCompletelyDestroyed (exprNode p_fexp, sRef p_fref, bool p_topLevel,
1267 fileloc p_loc, int p_depth, dscCode p_desc,
1270 bool checkGlobalDestroyed (sRef fref, fileloc loc)
1272 return (checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1273 loc, 0, DSC_GLOB, FALSE));
1276 void checkLocalDestroyed (sRef fref, fileloc loc)
1278 if (sRef_isObserver (fref) || sRef_isExposed (fref)
1279 || sRef_isPartial (fref))
1285 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1286 loc, 0, DSC_LOCAL, FALSE);
1290 void checkStructDestroyed (sRef fref, fileloc loc)
1292 DPRINTF (("Check struct destroyed: %s", sRef_unparse (fref)));
1294 if (sRef_isObserver (fref) || sRef_isExposed (fref)
1295 || sRef_isPartial (fref))
1297 DPRINTF (("Its exposed!"));;
1301 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1302 loc, 0, DSC_STRUCT, FALSE);
1307 checkCompletelyDestroyed (exprNode fexp, sRef fref, bool topLevel,
1308 fileloc loc, int depth,
1309 dscCode desc, bool hideErrors)
1313 DPRINTF (("Check completely destroyed: %s", sRef_unparseFull (fref)));
1315 if (depth > MAXDEPTH)
1317 llquietbug (message ("checkCompletelyDestroyed: too deep: %s / %q",
1318 exprNode_unparse (fexp),
1319 sRef_unparseFull (fref)));
1323 if (!sRef_isKnown (fref)) return TRUE;
1325 /* evans 2001-03-24: added this. Definitely null values are always destroyed. */
1327 if (sRef_isDefinitelyNull (fref))
1332 if (sRef_isDependent (fref) || sRef_isShared (fref) || sRef_isKept (fref))
1339 ** evans 2001-03-24: if there is a dependent reference to this storage,
1340 ** no need to destroy, but make it responsible.
1343 sRef depRef = dependentReference (fref);
1345 DPRINTF (("Destroyed? %s / %s",
1346 sRef_unparseFull (fref),
1347 sRef_unparseFull (depRef)));
1349 DPRINTF (("Aliases: %s", usymtab_unparseAliases ()));
1351 if (sRef_isValid (depRef))
1354 ** If the referenced storage was not dependent, we make
1355 ** the reference the owner since it must eventually be
1359 if (!sRef_isDependent (depRef))
1361 sRef_setOnly (depRef, loc); /* could be owned? */
1364 sRef_kill (fref, loc);
1369 if (sRef_isPdefined (fref) && !context_getFlag (FLG_STRICTDESTROY))
1371 DPRINTF (("Partial: %s", sRef_unparseFull (fref)));
1372 hideErrors = TRUE; /* Don't report any more errors, but still change ownership. */
1375 if (usymtab_isDefinitelyNull (fref))
1377 DPRINTF (("Probably null!"));
1381 if (!context_getFlag (FLG_COMPDESTROY)) return TRUE;
1382 if (!context_getFlag (FLG_MUSTFREE)) return TRUE;
1384 ct = ctype_realType (sRef_getType (fref));
1386 DPRINTF (("Here: %s", ctype_unparse (ct)));
1390 bool docheck = FALSE;
1393 if (sRef_isFresh (fref) || sRef_isOnly (fref))
1397 DPRINTF (("Here: %s", ctype_unparse (ct)));
1398 if (sRef_isDead (fref)
1399 || sRef_isUnuseable (fref)
1400 || sRef_definitelyNull (fref)
1401 || sRef_isObserver (fref)
1402 || sRef_isExposed (fref))
1410 if (sRef_isPossiblyDead (fref) || sRef_isRelDef (fref))
1412 if (exprNode_isDefined (fexp))
1418 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1419 message ("Only storage %q (type %s) derived from %s "
1420 "may not have been released: %s",
1421 sRef_unparse (fref),
1422 ctype_unparse (sRef_getType (fref)),
1423 dscCode_unparse (desc),
1424 exprNode_unparse (fexp)),
1433 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1435 ("Only storage %q (type %s) derived from %s "
1436 "may not have been released",
1437 sRef_unparse (fref),
1438 ctype_unparse (sRef_getType (fref)),
1439 dscCode_unparse (desc)),
1445 sRef_kill (fref, loc); /* prevent further errors */
1450 if (sRef_isStateUndefined (fref))
1452 DPRINTF (("Here: %s", ctype_unparse (ct)));
1457 if (exprNode_isDefined (fexp))
1459 DPRINTF (("Here: %s", sRef_unparseFull (fref)));
1466 message ("Only storage %q (type %s) derived from %s "
1467 "is not released (memory leak): %s",
1468 sRef_unparse (fref),
1469 ctype_unparse (sRef_getType (fref)),
1470 dscCode_unparse (desc),
1471 exprNode_unparse (fexp)),
1481 message ("Only storage %q (type %s) derived from %s "
1482 "is not released (memory leak)",
1483 sRef_unparse (fref),
1484 ctype_unparse (sRef_getType (fref)),
1485 dscCode_unparse (desc)),
1493 /* sRef_kill (fref, loc); */ /* prevent further errors */
1494 DPRINTF (("Killed: %s", sRef_unparseFull (fref)));
1499 DPRINTF (("Here: %s", ctype_unparse (ct)));
1503 if (/*! evs-2001-03-24 sRef_isAnyDefined (fref) || */
1505 || (sRef_isPdefined (fref)
1506 && sRefSet_isEmpty (sRef_derivedFields (fref))))
1508 DPRINTF (("Here: %s [%s / %s]",
1509 sRef_unparseFull (fref),
1510 bool_unparse (sRef_isAnyDefined (fref)),
1511 bool_unparse (sRef_isDead (fref))));
1516 DPRINTF (("Here..."));
1518 if (ctype_isPointer (ct))
1520 sRef fptr = sRef_constructDeadDeref (fref);
1523 res = checkCompletelyDestroyed (fexp, fptr, FALSE, loc,
1524 depth + 1, desc, hideErrors);
1528 else if (ctype_isArray (ct))
1530 if ((sRef_isStateUnknown (fref) || sRef_isAllocated (fref))
1531 && !sRef_hasDerived (fref))
1534 ** Bogosity necessary to prevent infinite depth.
1541 sRef farr = sRef_constructDeadDeref (fref);
1543 return (checkCompletelyDestroyed (fexp, farr, FALSE, loc,
1544 depth + 1, desc, hideErrors));
1547 else if (ctype_isStruct (ct))
1550 ** for structures, each field must be completely destroyed
1554 uentryList fields = ctype_getFields (ct);
1556 DPRINTF (("Struct fields: %s", uentryList_unparse (fields)));
1558 if (depth >= MAXDEPTH)
1560 llquietbug (message ("checkCompletelyDestroyed (fields): too deep: %s / %q",
1561 exprNode_unparse (fexp),
1562 sRef_unparseFull (fref)));
1568 uentryList_elements (fields, ue)
1570 sRef field = sRef_makeField (fref, uentry_rawName (ue));
1573 ** note order of && operands --- want to report multiple errors
1576 DPRINTF (("Check field: %s", sRef_unparseFull (field)));
1578 isOk = (checkCompletelyDestroyed (fexp, field, FALSE, loc,
1579 depth + 1, desc, hideErrors)
1581 } end_uentryList_elements;
1593 checkReturnTransfer (exprNode fexp, uentry rval)
1595 sRef uref = uentry_getSref (rval);
1596 sRef rref = sRef_makeNew (sRef_getType (uref), uref, cstring_undefined);
1597 uentry fcn = context_getHeader ();
1598 sRef fref = exprNode_getSref (fexp);
1599 stateClauseList clauses = uentry_getStateClauseList (fcn);
1601 DPRINTF (("Check return: %s as %s = %s",
1602 exprNode_unparse (fexp),
1603 sRef_unparseFull (uref),
1604 sRef_unparseFull (rref)));
1606 /* evans 2001-07-18: removed: if (sRef_isStateSpecial (rref)) */
1608 DPRINTF (("Check state clauses: %s",
1609 stateClauseList_unparse (clauses)));
1611 stateClauseList_postElements (clauses, cl)
1613 if (stateClause_isGlobal (cl))
1617 else if (stateClause_setsMetaState (cl))
1619 sRefSet refs = stateClause_getRefs (cl);
1620 qual ql = stateClause_getMetaQual (cl);
1621 annotationInfo ainfo = qual_getAnnotationInfo (ql);
1622 metaStateInfo minfo = annotationInfo_getState (ainfo);
1623 cstring key = metaStateInfo_getName (minfo);
1624 int mvalue = annotationInfo_getValue (ainfo);
1626 DPRINTF (("Return check: %s", stateClause_unparse (cl)));
1628 sRefSet_elements (refs, el)
1630 sRef base = sRef_getRootBase (el);
1632 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
1634 if (sRef_isResult (base))
1636 sRef sr = sRef_fixBase (el, fref);
1638 if (!sRef_checkMetaStateValue (sr, key, mvalue))
1642 message ("Result state %q does not satisfy ensures "
1643 "clause: %q (state is %q, should be %s): %s",
1645 stateClause_unparse (cl),
1646 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
1648 metaStateInfo_unparseValue (minfo, mvalue),
1649 exprNode_unparse (fexp)),
1650 exprNode_loc (fexp)))
1652 sRef_showAliasInfo (sr);
1660 ** Non-results are checked in exit scope.
1663 } end_sRefSet_elements ;
1667 sRefSet refs = stateClause_getRefs (cl);
1668 sRefTest tst = stateClause_getPostTestFunction (cl);
1669 sRefMod modf = stateClause_getReturnEffectFunction (cl);
1671 DPRINTF (("Clause: %s / %s",
1672 stateClause_unparse (cl),
1673 sRefSet_unparse (refs)));
1675 sRefSet_elements (refs, el)
1677 sRef base = sRef_getRootBase (el);
1679 DPRINTF (("el: %s / %s", sRef_unparse (el),
1680 sRef_unparse (base)));
1682 if (sRef_isResult (base))
1684 sRef sr = sRef_fixBase (el, fref);
1686 if (tst != NULL && !(tst (sr)))
1689 (stateClause_postErrorCode (cl),
1690 message ("%s storage %q corresponds to "
1691 "storage %q listed in %q clause: %s",
1692 stateClause_postErrorString (cl, sr),
1695 stateClause_unparseKind (cl),
1696 exprNode_unparse (fexp)),
1697 exprNode_loc (fexp)))
1699 sRefShower ss = stateClause_getPostTestShower (cl);
1710 modf (sr, exprNode_loc (fexp));
1716 ** Non-results are checked in exit scope.
1719 } end_sRefSet_elements ;
1721 } end_stateClauseList_postElements ;
1723 if (ctype_isRealSU (exprNode_getType (fexp)))
1725 sRef ffref = exprNode_getSref (fexp);
1727 checkStructTransfer (exprNode_undefined, rref,
1729 exprNode_loc (fexp),
1734 (void) checkTransfer (fexp, exprNode_getSref (fexp),
1735 exprNode_undefined, rref,
1737 exprNode_loc (fexp), TT_FCNRETURN);
1742 checkPassstateClauseList (uentry ue, exprNode fexp, sRef fref, int argno)
1744 stateClauseList clauses = uentry_getStateClauseList (ue);
1746 DPRINTF (("Check pass special: %s / %s",
1747 exprNode_unparse (fexp), sRef_unparseFull (fref)));
1749 stateClauseList_preElements (clauses, cl)
1751 if (stateClause_isGlobal (cl))
1757 sRefSet refs = stateClause_getRefs (cl);
1758 sRefTest tst = stateClause_getPreTestFunction (cl);
1759 sRefMod modf = stateClause_getEffectFunction (cl);
1761 sRefSet_elements (refs, el)
1763 sRef base = sRef_getRootBase (el);
1765 if (sRef_isResult (base))
1767 ; /* nothing to check before */
1769 else if (sRef_isParam (base))
1771 if (sRef_getParam (base) == argno - 1)
1775 DPRINTF (("Fix base: %s / %s",
1776 sRef_unparseFull (el),
1777 sRef_unparseFull (fref)));
1779 sb = sRef_fixBase (el, fref);
1781 if (tst != NULL && !(tst(sb)))
1784 (stateClause_preErrorCode (cl),
1785 message ("%s storage %qcorresponds to "
1786 "storage listed in %q clause of "
1787 "called function: %s",
1788 stateClause_preErrorString (cl, sb),
1789 sRef_unparseOpt (sb),
1790 stateClause_unparseKind (cl),
1791 exprNode_unparse (fexp)),
1792 exprNode_loc (fexp));
1797 DPRINTF (("Fixing: %s", sRef_unparseFull (sb)));
1798 modf (sb, exprNode_loc (fexp));
1799 DPRINTF (("==> %s", sRef_unparseFull (sb)));
1807 } end_sRefSet_elements ;
1809 } end_stateClauseList_preElements ;
1811 DPRINTF (("After: %s", sRef_unparseFull (fref)));
1815 ** should not modify arg
1819 checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
1820 /*@dependent@*/ exprNode fcn, int argno, int totargs)
1822 sRef tref = uentry_getSref (arg);
1823 sRef fref = exprNode_getSref (fexp);
1825 bool isPartial = FALSE;
1826 bool isImpOut = FALSE;
1827 ctype ct = uentry_getType (arg);
1829 DPRINTF (("Check pass: %s -> %s",
1830 sRef_unparseFull (fref),
1831 sRef_unparseFull (tref)));
1835 atNumArgs = totargs;
1837 if (ctype_isElips (ct))
1842 DPRINTF (("Out arg: %s", bool_unparse (uentry_isOut (arg))));
1844 if (!ctype_isElips (ct) &&
1845 (ctype_isVoidPointer (ct) && uentry_isOut (arg) && sRef_isOnly (tref)))
1847 if (ctype_isRealAP (ct))
1849 if (sRef_aliasCheckSimplePred (sRef_isDead, fref))
1853 message ("Dead storage %qpassed as out parameter to %s: %s",
1854 sRef_unparseOpt (fref),
1855 exprNode_unparse (fcn),
1856 exprNode_unparse (fexp)),
1857 exprNode_loc (fexp)))
1859 if (sRef_isDead (fref))
1861 sRef_showStateInfo (fref);
1865 DPRINTF (("Not really dead!"));
1866 sRef_showStateInfo (fref);
1870 sRef_setAllocated (fref, exprNode_loc (fexp));
1872 else if (context_getFlag (FLG_STRICTUSERELEASED)
1873 && sRef_aliasCheckSimplePred (sRef_isPossiblyDead, fref))
1876 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1877 message ("Possibly dead storage %qpassed as out parameter: %s",
1878 sRef_unparseOpt (fref),
1879 exprNode_unparse (fexp)),
1880 exprNode_loc (fexp)))
1882 if (sRef_isPossiblyDead (fref))
1884 sRef_showStateInfo (fref);
1888 sRef_setAllocated (fref, exprNode_loc (fexp));
1890 else if (sRef_aliasCheckSimplePred (sRef_isStateUndefined, fref)
1891 || sRef_aliasCheckSimplePred (sRef_isUnuseable, fref))
1895 message ("Unallocated storage %qpassed as out parameter: %s",
1896 sRef_unparseOpt (fref),
1897 exprNode_unparse (fexp)),
1898 exprNode_loc (fexp));
1900 sRef_setAllocated (fref, exprNode_loc (fexp));
1908 (void) checkCompletelyDestroyed (fexp, fref, TRUE, exprNode_loc (fexp),
1909 0, DSC_PARAM, FALSE);
1911 /* make it defined now, so checkTransfer is okay */
1912 sRef_setDefined (fref, exprNode_loc (fexp));
1914 else if (uentry_isOut (arg))
1916 DPRINTF (("Here we are!"));
1918 if (ctype_isRealAP (ct)
1919 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1923 message ("Unallocated storage %qpassed as out parameter to %s: %s",
1924 sRef_unparseOpt (fref),
1925 exprNode_unparse (fcn),
1926 exprNode_unparse (fexp)),
1927 exprNode_loc (fexp));
1928 sRef_setAllocated (fref, exprNode_loc (fexp));
1930 else if (sRef_isDead (fref))
1934 message ("Dead storage %qpassed as out parameter to %s: %s",
1935 sRef_unparseOpt (fref),
1936 exprNode_unparse (fcn),
1937 exprNode_unparse (fexp)),
1938 exprNode_loc (fexp)))
1940 sRef_showStateInfo (fref);
1941 sRef_setAllocated (fref, exprNode_loc (fexp));
1944 else if (sRef_isPossiblyDead (fref))
1947 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1948 message ("Possibly dead storage %qpassed as out parameter to %s: %s",
1949 sRef_unparseOpt (fref),
1950 exprNode_unparse (fcn),
1951 exprNode_unparse (fexp)),
1952 exprNode_loc (fexp)))
1954 sRef_showStateInfo (fref);
1955 sRef_setAllocated (fref, exprNode_loc (fexp));
1965 else if (uentry_isPartial (arg))
1967 if (ctype_isRealAP (ct)
1968 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1972 message ("Unallocated storage %qpassed as partial parameter: %s",
1973 sRef_unparseOpt (fref),
1974 exprNode_unparse (fexp)),
1975 exprNode_loc (fexp));
1976 sRef_setAllocated (fref, exprNode_loc (fexp));
1978 else if (sRef_isDead (fref))
1982 message ("Dead storage %qpassed as partial parameter to %s: %s",
1983 sRef_unparseOpt (fref),
1984 exprNode_unparse (fcn),
1985 exprNode_unparse (fexp)),
1986 exprNode_loc (fexp)))
1988 sRef_showStateInfo (fref);
1989 sRef_setAllocated (fref, exprNode_loc (fexp));
1992 else if (sRef_isPossiblyDead (fref))
1995 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1996 message ("Possibly dead storage %qpassed as partial parameter to %s: %s",
1997 sRef_unparseOpt (fref),
1998 exprNode_unparse (fcn),
1999 exprNode_unparse (fexp)),
2000 exprNode_loc (fexp)))
2002 sRef_showStateInfo (fref);
2003 sRef_setAllocated (fref, exprNode_loc (fexp));
2013 else if (uentry_isStateSpecial (arg))
2015 uentry ue = exprNode_getUentry (fcn);
2017 if (ctype_isRealAP (ct)
2018 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
2022 message ("Unallocated storage %qpassed as special parameter: %s",
2023 sRef_unparseOpt (fref),
2024 exprNode_unparse (fexp)),
2025 exprNode_loc (fexp));
2026 sRef_setAllocated (fref, exprNode_loc (fexp));
2028 else if (sRef_isDead (fref))
2032 message ("Dead storage %qpassed as special parameter to %s: %s",
2033 sRef_unparseOpt (fref),
2034 exprNode_unparse (fcn),
2035 exprNode_unparse (fexp)),
2036 exprNode_loc (fexp)))
2038 sRef_showStateInfo (fref);
2039 sRef_setAllocated (fref, exprNode_loc (fexp));
2042 else if (sRef_isPossiblyDead (fref))
2045 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
2046 message ("Possibly dead storage %qpassed as special parameter to %s: %s",
2047 sRef_unparseOpt (fref),
2048 exprNode_unparse (fcn),
2049 exprNode_unparse (fexp)),
2050 exprNode_loc (fexp)))
2052 sRef_showStateInfo (fref);
2053 sRef_setAllocated (fref, exprNode_loc (fexp));
2061 if (uentry_hasStateClauseList (ue))
2063 checkPassstateClauseList (ue, fexp, fref, argno);
2068 else if (sRef_isStateDefined (tref))
2070 exprNode_checkUseParam (fexp);
2074 if (isSpec || (!context_getFlag (FLG_IMPOUTS)))
2076 exprNode_checkUseParam (fexp);
2080 if (!sRef_isMacroParamRef (fref)
2081 && (ctype_isRealAP (ct)))
2083 if (sRef_isAddress (fref))
2085 if (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref))
2090 ("Unallocated address %qpassed as implicit "
2091 "out parameter: %s",
2092 sRef_unparseOpt (fref),
2093 exprNode_unparse (fexp)),
2094 exprNode_loc (fexp));
2095 sRef_setAllocated (fref, exprNode_loc (fexp));
2099 /* yes, I really mean this! */
2100 tref = sRef_copy (tref);
2101 sRef_setAllocated (tref, exprNode_loc (fexp));
2108 exprNode_checkUseParam (fexp);
2113 if (sRef_isNew (fref))
2115 alkind tkind = sRef_getAliasKind (tref);
2117 if ((sRef_isFresh (fref) || sRef_isOnly (fref))
2118 && !alkind_isOnly (tkind)
2119 && !alkind_isKeep (tkind)
2120 && !alkind_isOwned (tkind)
2121 && !alkind_isError (tkind)
2122 && !uentry_isReturned (arg))
2127 message ("New fresh storage %q(type %s) passed as %s (not released): %s",
2128 sRef_unparseOpt (fref),
2129 ctype_unparse (sRef_getType (fref)),
2130 alkind_unparse (sRef_getAliasKind (tref)),
2131 exprNode_unparse (fexp)),
2132 exprNode_loc (fexp));
2133 DPRINTF (("Fresh: %s", sRef_unparseFull (fref)));
2137 if (sRef_isNewRef (fref) && !sRef_isKillRef (tref))
2139 alkind ak = sRef_getAliasKind (tref);
2141 if (!alkind_isError (ak))
2145 message ("New reference %q(type %s) passed as %s (not released): %s",
2146 sRef_unparseOpt (fref),
2147 ctype_unparse (sRef_getType (fref)),
2148 alkind_unparse (sRef_getAliasKind (tref)),
2149 exprNode_unparse (fexp)),
2150 exprNode_loc (fexp));
2156 (void) checkTransfer (fexp, exprNode_getSref (fexp),
2157 exprNode_undefined, tref,
2159 exprNode_loc (fexp), TT_FCNPASS);
2162 fref = exprNode_getSref (fexp);
2164 if (isOut && !sRef_isDead (fref) && !sRef_isPossiblyDead (fref))
2168 if (ctype_isRealAP (sRef_getType (fref)))
2170 base = sRef_makePointer (fref);
2179 exprNode_checkMSet (fexp, base);
2183 exprNode_checkSet (fexp, base);
2186 if (sRef_isValid (base))
2190 sRef_clearDerived (base);
2191 sRef_setDefined (base, exprNode_loc (fexp));
2192 usymtab_clearAlias (base);
2193 sRef_setNullUnknown (base, exprNode_loc (fexp));
2199 if (sRef_isValid (fref))
2201 sRef_setPartial (fref, exprNode_loc (fexp));
2205 atFunction = exprNode_undefined;
2209 /* need to fixup here: derived refs could be bogus */
2210 /* (better to change sRef to not add derivs for "protected" ref) */
2212 uentry_fixupSref (arg);
2216 DPRINTF (("Check pass: ==> %s",
2217 sRef_unparseFull (fref)));
2221 checkGlobReturn (uentry glob)
2223 sRef_protectDerivs ();
2224 checkGlobTrans (glob, TT_GLOBRETURN);
2225 sRef_clearProtectDerivs ();
2228 void checkParamReturn (uentry actual)
2230 checkLeaveTrans (actual, TT_PARAMRETURN);
2233 void checkLoseRef (uentry actual)
2235 checkLeaveTrans (actual, TT_LEAVETRANS);
2239 checkLeaveTrans (uentry actual, transferKind transferType)
2241 sRef aref = uentry_getSref (actual);
2242 sRef origref = uentry_getOrigSref (actual);
2244 if (transferType == TT_PARAMRETURN
2245 && (sRef_isKeep (origref) || sRef_isOnly (origref)
2246 || sRef_isOwned (origref)))
2248 /* caller cannot use, nothing to check */
2252 if (sRef_isNSLocalVar (origref))
2258 DPRINTF (("Leave trans: %s", uentry_unparseFull (actual)));
2260 (void) checkCompletelyDefined (exprNode_undefined, aref, aref,
2261 exprNode_undefined, origref,
2263 g_currentloc, transferType,
2270 checkGlobTrans (uentry glob, transferKind type)
2272 sRef eref = uentry_getOrigSref (glob);
2274 (void) checkCompletelyDefined (exprNode_undefined, uentry_getSref (glob), uentry_getSref (glob),
2275 exprNode_undefined, eref,
2277 g_currentloc, type, 0, TRUE);
2281 ** For lhs of assignment, alias kind is set from basic type.
2286 fixAssignLhs (sRef s)
2288 sRef_resetStateComplete (s);
2291 static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srhs,
2295 ctype st = ctype_realType (sRef_getType (srhs));
2297 if (ctype_isSU (st) && ctype_isRealSU (sRef_getType (slhs))
2298 && ctype_match (sRef_getType (slhs), st))
2300 if (tt == TT_DOASSIGN && sRef_isStateDefined (srhs))
2302 sRef_setDefinedComplete (slhs, loc);
2305 if (sRef_isDependent (slhs)
2306 || sRef_isObserver (slhs)
2307 || sRef_isExposed (slhs))
2313 if (sRef_isLocalVar (slhs)
2314 && sRef_isFileOrGlobalScope (sRef_getRootBase (srhs)))
2316 sRef_setDependent (slhs, exprNode_loc (lhs));
2320 if (ctype_isUnion (st))
2322 sRef_setDefState (slhs, sRef_getDefState (srhs),
2323 exprNode_loc (lhs));
2325 sRefSet_realElements (sRef_derivedFields (srhs), sr)
2327 if (sRef_isField (sr))
2329 cstring fieldname = sRef_getField (sr);
2330 sRef lfld = sRef_makeField (slhs, fieldname);
2332 (void) checkTransfer (rhs, sr, lhs, lfld,
2334 exprNode_loc (lhs), tt);
2336 } end_sRefSet_realElements ;
2340 uentryList fields = ctype_getFields (st);
2342 uentryList_elements (fields, field)
2344 sRef rfld = sRef_makeField (srhs, uentry_rawName (field));
2345 sRef lfld = sRef_makeField (slhs, uentry_rawName (field));
2346 (void) checkTransfer (rhs, rfld, lhs, lfld,
2348 exprNode_loc (lhs), tt);
2349 } end_uentryList_elements ;
2352 if (sRef_isOnly (srhs))
2354 sRef_setKeptComplete (srhs, loc);
2362 checkInitTransfer (exprNode lhs, exprNode rhs)
2364 sRef slhs = exprNode_getSref (lhs);
2366 if (sRef_isFileOrGlobalScope (slhs) || (!sRef_isCvar (slhs)))
2368 (void) checkTransfer (rhs, exprNode_getSref (rhs),
2371 exprNode_loc (rhs), TT_GLOBINIT);
2375 checkAssignTransfer (lhs, rhs);
2380 checkAssignTransfer (exprNode lhs, exprNode rhs)
2382 sRef slhs = exprNode_getSref (lhs);
2383 sRef srhs = exprNode_getSref (rhs);
2384 sRef base = sRef_getBaseSafe (slhs);
2387 DPRINTF (("Check assign: %s = %s", exprNode_unparse (lhs),
2388 exprNode_unparse (rhs)));
2389 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2390 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2392 if (ctype_isRealSU (sRef_getType (srhs)))
2394 checkStructTransfer (lhs, slhs, rhs, srhs, exprNode_loc (lhs), TT_FIELDASSIGN);
2398 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2399 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2400 (void) checkTransfer (rhs, srhs, lhs, slhs,
2402 exprNode_loc (lhs), TT_DOASSIGN);
2403 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2404 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2407 if (sRef_isConst (srhs) && sRef_isLocalState (srhs))
2409 /* constants can match anything (e.g., NULL) */
2410 sRef_setAliasKind (slhs, AK_ERROR, fileloc_undefined);
2413 if (sRef_isValid (base) && sRef_isStateDefined (base))
2415 sRef_setPdefined (base, g_currentloc);
2418 if (sRef_isPartial (srhs))
2420 sRef_setPartial (slhs, exprNode_loc (rhs));
2423 ns = sRef_getNullState (srhs);
2425 if (nstate_possiblyNull (ns))
2427 if (usymtab_isGuarded (srhs))
2433 sRef_setNullStateInnerComplete (slhs, ns, exprNode_loc (rhs));
2435 if (sRef_isExposed (srhs) || sRef_isObserver (srhs))
2437 sRef_setExKind (slhs, sRef_getExKind (srhs), exprNode_loc (rhs));
2440 DPRINTF (("Done transfer: %s", sRef_unparseFull (slhs)));
2444 checkTransferNullAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2445 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2446 fileloc loc, transferKind transferType)
2448 alkind tkind = sRef_getAliasKind (tref);
2449 ctype ttyp = ctype_realType (sRef_getType (tref));
2451 if (ctype_isUnknown (ttyp))
2453 ttyp = exprNode_getType (texp);
2455 if (ctype_isUnknown (ttyp))
2457 ttyp = exprNode_getType (fexp);
2459 if (ctype_isUnknown (ttyp))
2461 ttyp = sRef_getType (fref);
2466 if (ctype_isFunction (ttyp) && (transferType == TT_FCNRETURN))
2468 ttyp = ctype_getReturnType (ttyp);
2472 ** check for null (don't need to check aliases??)
2475 if (sRef_possiblyNull (fref)
2476 && !usymtab_isGuarded (fref)
2477 && ctype_isRealAP (ttyp))
2479 if (!alkind_isLocal (tkind) && !alkind_isFresh (tkind)
2480 && !sRef_perhapsNull (tref)
2481 && !(transferType == TT_DOASSIGN))
2483 if (transferType == TT_GLOBINIT)
2485 if (sRef_isNotNull (tref))
2488 (FLG_SYNTAX, /*@i432 kuldge flag... */
2489 message ("%s %q initialized to %s value: %q",
2490 sRef_getScopeName (tref),
2491 sRef_unparse (tref),
2492 sRef_nullMessage (fref),
2493 generateText (fexp, texp, tref, transferType)),
2496 sRef_showNullInfo (fref);
2497 sRef_setNullError (tref);
2504 message ("%s %q initialized to %s value: %q",
2505 sRef_getScopeName (tref),
2506 sRef_unparse (tref),
2507 sRef_nullMessage (fref),
2508 generateText (fexp, texp, tref, transferType)),
2511 sRef_showNullInfo (fref);
2512 sRef_setNullError (tref);
2519 ((transferType == TT_FCNPASS) ? FLG_NULLPASS : FLG_NULLRET,
2520 message ("%q storage %q%s: %q",
2521 cstring_capitalize (sRef_nullMessage (fref)),
2522 sRef_unparseOpt (fref),
2523 transferNullMessage (transferType),
2524 generateText (fexp, texp, tref, transferType)),
2527 sRef_showNullInfo (fref);
2528 sRef_setNullError (fref);
2541 checkTransferAssignAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2542 /*@exposed@*/ sRef tref, exprNode texp, bool tfix,
2543 fileloc loc, transferKind transferType)
2545 alkind tkind = sRef_getAliasKind (tref);
2548 ** Assignment to same --- no errors, or state changes.
2549 ** This can happen when returned params are used.
2552 if (sRef_sameName (fref, tref))
2554 sRef_copyState (tref, fref);
2558 if ((alkind_isOnly (tkind) || alkind_isFresh (tkind)
2559 || alkind_isNewRef (tkind) || alkind_isOwned (tkind))
2560 && !(sRef_isDead (tref)
2561 || sRef_isStateUndefined (tref)
2562 || sRef_isUnuseable (tref)
2563 || sRef_isPartial (tref)
2564 || sRef_definitelyNull (tref)
2565 || sRef_isStackAllocated (tref)
2566 || sRef_isAllocIndexRef (tref))
2567 && !(sRef_same (fref, tref)) /* okay to assign to self (returned params) */
2568 && !(usymtab_isDefinitelyNull (tref)))
2570 if (context_getFlag (FLG_MUSTFREE))
2572 if (canLoseReference (tref, loc))
2578 if (sRef_hasLastReference (tref))
2582 message ("Last reference %q to %s storage %q(type %s) not released "
2583 "before assignment: %q",
2584 sRef_unparse (tref),
2585 alkind_unparse (tkind),
2586 sRef_unparseOpt (sRef_getAliasInfoRef (tref)),
2587 ctype_unparse (sRef_getType (tref)),
2588 generateText (fexp, texp, tref, transferType)),
2591 sRef_showRefLost (tref);
2596 if (context_inGlobalScope ())
2598 /* no errors for static initializations */
2603 ** don't report this error for a[i], since it could
2604 ** be a new element.
2607 if (alkind_isNewRef (tkind))
2612 ("%q %q(type %s) not released before assignment: %q",
2614 (alkind_isKillRef (sRef_getOrigAliasKind (tref))
2615 ? "Kill reference parameter" : "New reference"),
2616 sRef_unparseOpt (tref),
2617 ctype_unparse (sRef_getType (tref)),
2618 generateText (fexp, texp, tref, transferType)),
2621 sRef_showAliasInfo (tref);
2622 sRef_setAliasKind (tref, AK_ERROR, loc);
2626 (!(sRef_isUnknownArrayFetch (tref)
2627 && !context_getFlag (FLG_STRICTDESTROY))
2628 && !sRef_isUnionField (tref)
2629 && !sRef_isRelDef (tref)
2633 ("%s storage %q(type %s) not released before assignment: %q",
2634 alkind_capName (tkind),
2635 sRef_unparseOpt (tref),
2636 ctype_unparse (sRef_getType (tref)),
2637 generateText (fexp, texp, tref, transferType)),
2640 sRef_showAliasInfo (tref);
2652 fixAssignLhs (tref);
2654 if (sRef_isRefCounted (tref)) /* tkind might not be correct now */
2656 if (sRef_isNewRef (fref))
2658 sRef_setAliasKind (tref, AK_NEWREF, loc);
2660 else if (sRef_isConst (fref))
2662 /* for now, constants are not ref counted */
2663 sRef_setAliasKind (tref, AK_ERROR, loc);
2670 if (!sRef_isNSLocalVar (tref)
2671 && sRef_isRefCounted (fref)
2672 && sRef_isStateDefined (fref))
2676 message ("New reference %qto reference counted storage: %q",
2677 sRef_unparseOpt (tref),
2678 generateText (fexp, texp, tref, transferType)),
2684 ** Not for structures and unions, since assignments copy.
2687 if (sRef_isStack (fref)
2688 && !ctype_isSU (ctype_realType (sRef_getType (fref))))
2690 sRef_setAliasKindComplete (tref, AK_STACK, loc);
2693 if (sRef_isNSLocalVar (tref)
2694 && !sRef_isOwned (tref) /*< should only apply to static >*/
2695 && ctype_isMutable (sRef_getType (tref)))
2697 if (sRef_isOnly (fref) && sRef_isNew (fref))
2701 sRef_setFresh (tref, loc);
2708 ** requires sRef_isOnly (fref)
2712 checkOnlyTransferAux (sRef fref, exprNode fexp, bool ffix,
2713 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2714 fileloc loc, transferKind transferType)
2716 alkind tkind = sRef_getAliasKind (tref);
2718 if (sRef_isExposed (tref) || sRef_isObserver (tref))
2720 if (transferType == TT_FCNRETURN && sRef_isNew (fref)
2721 && !alkind_isError (tkind))
2725 message ("Only storage %q%q (will not be released): %q",
2726 sRef_unparseOpt (fref),
2727 transferErrorMessage (transferType, tkind),
2728 generateText (fexp, texp, tref, transferType)),
2731 sRef_showAliasInfo (fref);
2735 /* no errors for exposed transfers (is this good enough?) */
2737 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind) || alkind_isOwned (tkind))
2741 else if ((transferType == TT_FCNPASS)
2742 && (alkind_isUnknown (tkind)
2743 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2745 if (sRef_isFresh (fref)
2746 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2748 if (!ffix) sRef_setAliasKind (fref, AK_UNKNOWN, loc);
2751 else if (alkind_isLocal (tkind)
2752 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2754 if ((transferType == TT_DOASSIGN)
2755 && sRef_isNew (fref)
2756 && sRef_isOnly (fref))
2760 if (alkind_isUnknown (tkind)
2761 && sRef_isFileOrGlobalScope (sRef_getRootBase (tref)))
2764 (FLG_ONLYUNQGLOBALTRANS,
2765 message ("Only storage %q%q: %q",
2766 sRef_unparseOpt (fref),
2767 transferErrorMessage (transferType, tkind),
2768 generateText (fexp, texp, tref, transferType)),
2771 sRef_showAliasInfo (fref);
2772 sRef_setAliasKind (tref, AK_ERROR, loc);
2777 if (!error && !ffix)
2779 sRef_setFresh (tref, loc);
2784 if (alkind_isLocal (tkind))
2786 if (sRef_sameName (tref, fref))
2788 ; /* don't set this --- corresponds to return transfer */
2793 ** Don't set local to dependent. Error will
2794 ** be detected through aliasing. Except for
2798 if (!tfix && sRef_isThroughArrayFetch (fref)
2799 && context_getFlag (FLG_DEPARRAYS))
2801 sRef_setDependent (tref, loc);
2809 message ("Only storage %q%q: %q",
2810 sRef_unparseOpt (fref),
2811 transferErrorMessage (transferType, tkind),
2812 generateText (fexp, texp, tref, transferType)),
2815 sRef_showAliasInfo (fref);
2822 if (alkind_isError (tkind)
2823 || (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT)))
2825 flagcode_recordSuppressed (FLG_ONLYTRANS);
2829 if ((alkind_isKept (tkind) || alkind_isStack (tkind)
2830 || alkind_isDependent (tkind))
2831 && sRef_isNSLocalVar (tref))
2839 message ("Only storage %q%q: %q",
2840 sRef_unparseOpt (fref),
2841 transferErrorMessage (transferType, tkind),
2842 generateText (fexp, texp, tref, transferType)),
2845 sRef_showAliasInfo (fref);
2847 if (transferType == TT_DOASSIGN)
2850 ** alias kind unknown to suppress future messages
2853 if (!ffix && sRef_isNSLocalVar (sRef_getRootBase (fref)))
2855 sRef_clearAliasKind (fref);
2865 ** ??? same as checkOnly ?
2869 checkOwnedTransferAux (sRef fref, exprNode fexp, bool ffix,
2870 sRef tref, exprNode texp, bool tfix,
2871 fileloc loc, transferKind transferType)
2873 alkind tkind = sRef_getAliasKind (tref);
2875 if (sRef_isExposed (tref) || sRef_isObserver (tref))
2877 if (transferType == TT_FCNRETURN && sRef_isNew (fref))
2881 message ("Owned storage %q%q (will not be released): %q",
2882 sRef_unparseOpt (fref),
2883 transferErrorMessage (transferType, tkind),
2884 generateText (fexp, texp, tref, transferType)),
2887 sRef_showAliasInfo (fref);
2891 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind)
2892 || alkind_isDependent (tkind)
2893 || alkind_isOwned (tkind))
2897 else if (alkind_isLocal (tkind)
2898 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2900 if ((transferType == TT_DOASSIGN)
2901 && sRef_isNew (fref) && sRef_isOnly (fref))
2905 sRef_setFresh (tref, loc);
2912 else if ((transferType == TT_FCNPASS)
2913 && (alkind_isUnknown (tkind)
2914 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2916 if (sRef_isFresh (fref)
2917 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2919 if (!ffix) { sRef_clearAliasKind (fref); }
2924 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2926 flagcode_recordSuppressed (FLG_OWNEDTRANS);
2930 if (alkind_isKept (tkind) && sRef_isNSLocalVar (tref))
2938 message ("Owned storage %q%q: %q",
2939 sRef_unparseOpt (fref),
2940 transferErrorMessage (transferType, tkind),
2941 generateText (fexp, texp, tref, transferType)),
2946 if (transferType == TT_DOASSIGN)
2949 ** alias kind unknown to suppress future messages
2952 if (!ffix) { sRef_clearAliasKind (fref); }
2958 checkFreshTransferAux (sRef fref, exprNode fexp, bool ffix,
2959 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2960 fileloc loc, transferKind transferType)
2962 alkind tkind = sRef_getAliasKind (tref);
2965 ** error to return fresh as non-only
2968 if (transferType == TT_FCNRETURN
2969 && !(alkind_isOnly (tkind) || alkind_isNewRef (tkind)))
2971 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2973 flagcode_recordSuppressed (FLG_NEWREFTRANS);
2977 if (alkind_isError (tkind))
2981 sRef_killComplete (fref, loc);
2984 else if (alkind_isRefCounted (tkind))
2989 ("New reference returned without newref qualifier: %q",
2990 generateText (fexp, texp, tref, transferType)),
2993 sRef_showAliasInfo (fref);
2994 sRef_killComplete (fref, loc);
3001 message ("Fresh storage %q (should be only): %q",
3002 transferErrorMessage (transferType, tkind),
3003 generateText (fexp, texp, tref, transferType)),
3006 sRef_showAliasInfo (fref);
3007 sRef_killComplete (fref, loc);
3014 ** Okay to assign fresh to only, shared or unqualified.
3016 ** should generate other errors?
3019 if (alkind_isOnly (tkind))
3021 if (transferType == TT_DOASSIGN && !sRef_isFileOrGlobalScope (tref))
3025 if (!sRef_isNSLocalVar (tref))
3027 sRef_setKeptComplete (fref, loc);
3033 if (sRef_isConst (fref))
3041 sRef_killComplete (fref, loc);
3046 else if (alkind_isOwned (tkind))
3050 sRef_setDependentComplete (fref, loc);
3053 else if (alkind_isRefCounted (tkind)
3054 && (transferType == TT_FCNRETURN) && sRef_isFresh (fref))
3058 sRef_killComplete (fref, loc);
3061 else if (alkind_isKeep (tkind))
3065 if (!sRef_isNSLocalVar (tref))
3067 sRef_setKeptComplete (fref, loc);
3071 else if (alkind_isShared (tkind))
3073 if (!ffix) { sRef_setShared (fref, loc); }
3075 else if (alkind_isLocal (tkind) || alkind_isUnknown (tkind))
3077 if (transferType == TT_DOASSIGN || transferType == TT_FCNRETURN)
3080 ** local shares fresh. Make it owned/dependent.
3085 sRef_setOwned (tref, loc);
3090 sRef_setDependentComplete (fref, loc);
3093 /* NO! sRef_clearAliasKind (fref); */
3097 if (context_getFlag (FLG_PASSUNKNOWN))
3099 sRef_clearAliasKind (fref);
3110 checkTransferExposure (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
3111 sRef tref, exprNode texp, bool tfix,
3113 transferKind transferType)
3115 alkind fkind = sRef_getAliasKind (fref);
3116 alkind tkind = sRef_getAliasKind (tref);
3117 exkind tekind = sRef_getExKind (tref);
3119 if (sRef_isObserver (fref) && ctype_isMutable (sRef_getType (fref)))
3122 ** observer -> exposed or observer
3126 ** observer -> temp is okay [NO! really? only in function calls]
3129 if (sRef_isExposed (tref) || sRef_isObserver (tref)
3130 || alkind_isLocal (tkind))
3134 if ((transferType == TT_DOASSIGN) && alkind_isLocal (tkind))
3138 sRef_setAliasKindComplete (tref, fkind, loc);
3144 if (transferType == TT_FCNRETURN
3145 || transferType == TT_DOASSIGN
3146 || transferType == TT_FIELDASSIGN
3147 || transferType == TT_GLOBINIT)
3149 bool hasError = FALSE;
3151 if (exprNode_isStringLiteral (fexp)
3152 && transferType == TT_GLOBINIT)
3154 hasError = optgenerror
3156 message ("Read-only string literal storage %q%q: %q",
3157 sRef_unparseOpt (fref),
3158 transferErrorExpMessage (transferType, tekind),
3159 generateText (fexp, texp, tref, transferType)),
3162 sRef_setAliasKind (fref, AK_ERROR, fileloc_undefined);
3166 if ((transferType == TT_DOASSIGN
3167 || transferType == TT_FIELDASSIGN)
3168 && (sRef_isNSLocalVar (tref)
3169 || (exprNode_isStringLiteral (fexp)
3170 && ctype_isRealArray (exprNode_getType (texp)))))
3172 ; /* No error for local assignment or assignment
3173 to static array (copies string). */
3177 if (exprNode_isStringLiteral (fexp))
3179 hasError = optgenerror
3182 ("Read-only string literal storage %q%q: %q",
3183 sRef_unparseOpt (fref),
3184 transferErrorExpMessage (transferType, tekind),
3185 generateText (fexp, texp, tref, transferType)),
3192 hasError = optgenerror
3195 ("Observer storage %q%q: %q",
3196 sRef_unparseOpt (fref),
3197 transferErrorExpMessage (transferType, tekind),
3198 generateText (fexp, texp, tref, transferType)),
3206 if (transferType != TT_GLOBINIT)
3208 sRef_showExpInfo (fref);
3209 sRef_setAliasKind (tref, AK_ERROR, loc);
3214 if (transferType == TT_DOASSIGN && !tfix)
3216 DPRINTF (("Setting unknown!"));
3217 /* sRef_setAliasKind (tref, AK_ERROR, loc); */
3221 else /* TT_FCNPASS */
3223 llassert (transferType == TT_FCNPASS);
3225 if (alkind_isTemp (tkind)
3226 || alkind_isDependent (tkind)
3227 || alkind_isRefCounted (tkind))
3233 if (!alkind_isError (tkind))
3237 message ("Observer storage %q%q: %q",
3238 sRef_unparseOpt (fref),
3239 transferErrorMessage (transferType, tkind),
3240 generateText (fexp, texp, tref, transferType)),
3243 sRef_showExpInfo (fref);
3244 sRef_clearAliasState (fref, loc);
3251 else if (sRef_isExposed (fref) && ctype_isMutable (sRef_getType (fref)))
3253 if (transferType == TT_FCNRETURN)
3255 if (!(sRef_isExposed (tref) || sRef_isObserver (tref)
3256 || sRef_isParam (fref)))
3260 message ("Exposed storage %q%q: %q",
3261 sRef_unparseOpt (fref),
3262 transferErrorExpMessage (transferType, tekind),
3263 generateText (fexp, texp, tref, transferType)),
3266 sRef_showExpInfo (fref);
3270 else if (transferType == TT_FCNPASS)
3272 if (!(sRef_isExposed (tref)
3273 || sRef_isObserver (tref)
3274 || (alkind_isUnknown (tkind)
3275 || alkind_isDependent (tkind)
3276 || alkind_isTemp (tkind)
3277 || alkind_isKillRef (tkind)
3278 || alkind_isRefCounted (tkind))))
3280 if (alkind_isUnique (tkind) || alkind_isError (tkind))
3287 message ("Exposed storage %q%q: %q",
3288 sRef_unparseOpt (fref),
3289 transferErrorMessage (transferType, tkind),
3290 generateText (fexp, texp, tref, transferType)),
3293 sRef_showExpInfo (fref);
3294 sRef_clearAliasState (fref, loc);
3304 else if (transferType == TT_DOASSIGN)
3306 if (!(sRef_isExposed (tref)
3307 || !sRef_isCvar (tref)
3308 || (alkind_isUnknown (tkind)
3309 || alkind_isDependent (tkind)
3310 || alkind_isRefCounted (tkind)
3311 || alkind_isNewRef (tkind)
3312 || alkind_isFresh (tkind)
3313 || alkind_isLocal (tkind))))
3317 message ("Exposed storage %q%q: %q",
3318 sRef_unparseOpt (fref),
3319 transferErrorExpMessage (transferType, tekind),
3320 generateText (fexp, texp, tref, transferType)),
3323 sRef_showExpInfo (fref);
3326 if (!tfix) { sRef_setExposed (tref, loc); }
3330 llassert (transferType == TT_GLOBPASS
3331 || transferType == TT_GLOBRETURN
3332 || transferType == TT_PARAMRETURN
3333 || transferType == TT_LEAVETRANS
3334 || transferType == TT_GLOBINIT);
3344 ** returns TRUE if there is no error reported
3346 ** if fixt, don't change tref (except if error reported.)
3347 ** if fixf, don't change fref (except if error reported.)
3351 checkTransferAux (exprNode fexp, /*@exposed@*/ sRef fref, bool ffix,
3352 exprNode texp, /*@exposed@*/ sRef tref, bool tfix,
3353 fileloc loc, transferKind transferType)
3357 bool isassign = (transferType == TT_DOASSIGN);
3358 bool isfieldassign = (transferType == TT_FIELDASSIGN);
3359 bool iseitherassign = isassign || (transferType == TT_FIELDASSIGN);
3360 bool isfcnpass = (transferType == TT_FCNPASS);
3361 bool isfcnreturn = (transferType == TT_FCNRETURN);
3368 checkTransferNullAux (fref, fexp, ffix, tref, texp, tfix,
3375 checkTransferAssignAux (fref, fexp, ffix, tref, texp, tfix,
3380 ** Check for definition
3384 ** errors passing out params already detected in checkAnyCall
3392 || (!sRef_isNSLocalVar (tref)
3393 && (sRef_isAnyDefined (tref) || !sRef_stateKnown (tref))))
3397 if (!ynm_toBoolRelaxed
3398 (checkCompletelyDefined (fexp, fref, fref,
3401 loc, transferType, 0, TRUE)))
3409 if (defok && iseitherassign)
3411 sRef_setDefState (tref, sRef_getDefState (fref), loc);
3420 checkTransferExposure (fref, fexp, ffix, tref, texp, tfix,
3423 fkind = sRef_getAliasKind (fref);
3424 tkind = sRef_getAliasKind (tref);
3430 if (alkind_isOnly (fkind))
3433 checkOnlyTransferAux (fref, fexp, ffix,
3437 else if (alkind_isFresh (fkind))
3440 checkFreshTransferAux (fref, fexp, ffix,
3444 else if (alkind_isOwned (fkind))
3447 checkOwnedTransferAux (fref, fexp, ffix,
3451 else if (alkind_isDependent (fkind))
3455 (sRef_isExposed (tref) || sRef_isObserver (tref)))
3459 else if ((alkind_isOnly (tkind) || alkind_isKeep (tkind)
3460 || alkind_isOwned (tkind))
3461 || (!isfcnpass && alkind_isTemp (tkind)))
3465 if (sRef_isLocalVar (fref))
3467 sRef depRef = dependentReference (fref);
3469 if (sRef_isValid (depRef) && sRef_isLocalVar (depRef))
3472 sRef_kill (depRef, loc);
3473 sRef_kill (fref, loc);
3483 if (canLoseLocalReference (fref, loc))
3491 (FLG_DEPENDENTTRANS,
3492 message ("%s storage %q%q: %q",
3493 alkind_capName (fkind),
3494 sRef_unparseOpt (fref),
3495 transferErrorMessage (transferType, tkind),
3496 generateText (fexp, texp, tref, transferType)),
3499 DPRINTF (("Here: %s / %s",
3500 sRef_unparseFull (fref),
3501 sRef_unparseFull (tref)));
3503 sRef_showAliasInfo (fref);
3509 if (isassign && (alkind_isFresh (tkind) || alkind_isLocal (tkind)))
3513 sRef_setDependent (tref, loc);
3518 else if (alkind_isShared (fkind))
3525 if (alkind_isOnly (tkind)
3527 && (!(sRef_isObserver (tref) || sRef_isExposed (tref))
3528 && alkind_isTemp (tkind))))
3532 message ("%s storage %q%q: %q",
3533 alkind_capName (fkind),
3534 sRef_unparseOpt (fref),
3535 transferErrorMessage (transferType, tkind),
3536 generateText (fexp, texp, tref, transferType)),
3539 sRef_showAliasInfo (fref);
3544 if (alkind_isFresh (tkind) || alkind_isLocal (tkind))
3546 sRef_setShared (tref, loc);
3550 else if (alkind_isKeep (fkind))
3554 if (alkind_isKeep (tkind)
3555 || alkind_isLocal (tkind)
3556 || (isfcnreturn && sRef_isExposed (tref))
3558 && (alkind_isOnly (tkind) || alkind_isOwned (tkind))))
3560 sRef_setKept (fref, loc);
3563 && (alkind_isTemp (tkind) || alkind_isOwned (tkind)))
3569 if (!alkind_isError (tkind))
3573 message ("%s storage %q: %q",
3574 alkind_capName (fkind),
3575 transferErrorMessage (transferType, tkind),
3576 generateText (fexp, texp, tref, transferType)),
3579 sRef_showAliasInfo (fref);
3584 else if (alkind_isTemp (fkind) || alkind_isKept (fkind))
3590 if (alkind_isOnly (tkind)
3591 || alkind_isShared (tkind)
3592 || (alkind_isTemp (fkind)
3593 && !isfcnreturn && alkind_isDependent (tkind))
3594 || alkind_isOwned (tkind)
3595 || alkind_isKeep (tkind))
3597 if (!exprNode_isNullValue (fexp)
3598 && (ctype_isMutable (exprNode_getType (fexp))
3599 || (ctype_isArray (exprNode_getType (fexp))
3600 && sRef_isParam (fref)))
3601 && (!iseitherassign || sRef_isReference (tref)))
3603 if (sRef_isThroughArrayFetch (fref))
3606 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3607 FLG_STRICTUSERELEASED,
3608 message ("%s storage %q%q: %q",
3609 alkind_capName (fkind),
3610 sRef_unparseOpt (fref),
3611 transferErrorMessage (transferType, tkind),
3612 generateText (fexp, texp, tref, transferType)),
3615 sRef_showAliasInfo (fref);
3621 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3622 message ("%s storage %q%q: %q",
3623 alkind_capName (fkind),
3624 sRef_unparseOpt (fref),
3625 transferErrorMessage (transferType, tkind),
3626 generateText (fexp, texp, tref, transferType)),
3629 sRef_showAliasInfo (fref);
3635 else if (alkind_isRefCounted (fkind) || alkind_isKillRef (fkind))
3637 if (alkind_isNewRef (tkind))
3640 ** check that the refs field has been modified
3643 if (!sRef_isConst (fref))
3647 message ("Reference counted storage returned without modifying "
3648 "reference count: %s",
3649 exprNode_unparse (fexp)),
3653 else if (iseitherassign)
3655 if (alkind_isRefCounted (fkind))
3657 if (!sRef_isLocalVar (tref))
3662 ("Assignment to non-local from reference counted storage: %s",
3663 exprNode_unparse (fexp)),
3665 ("Reference counted storage should call a function returning "
3666 "a newref instead of direct assignments."),
3677 if (alkind_isRefCounted (tkind) || alkind_isTemp (tkind))
3679 /* okay --- no change in state */
3681 else if (alkind_isKillRef (tkind))
3683 if (!ffix && !tfix && !(transferType == TT_FCNRETURN))
3685 sRef_killComplete (fref, loc);
3690 if (!alkind_isError (tkind))
3694 message ("Reference counted storage %q: %q",
3695 transferErrorMessage (transferType, tkind),
3696 generateText (fexp, texp, tref, transferType)),
3709 if (alkind_isOnly (tkind) || alkind_isKeep (tkind))
3711 if (sRef_isAddress (fref))
3714 (FLG_IMMEDIATETRANS,
3715 message ("Immediate address %q %q: %q",
3716 sRef_unparse (fref),
3717 transferErrorMessage (transferType, tkind),
3718 generateText (fexp, texp, tref, transferType)),
3721 sRef_setAliasKind (fref, AK_ERROR, loc);
3725 if ((alkind_isUnknown (fkind) || alkind_isStatic (fkind))
3726 && !sRef_isDefinitelyNull (fref)
3728 && (!exprNode_isNullValue (fexp)))
3730 flagcode errkind = alkind_isStatic (fkind)
3731 ? FLG_STATICTRANS : FLG_UNKNOWNTRANS;
3733 if (transferType == TT_GLOBINIT)
3735 if (errkind == FLG_STATICTRANS)
3737 errkind = FLG_STATICINITTRANS;
3741 errkind = FLG_UNKNOWNINITTRANS;
3747 message ("%s storage %s %q: %q",
3748 alkind_capName (fkind),
3749 exprNode_unparse (fexp),
3750 transferErrorMessage (transferType, tkind),
3751 generateText (fexp, texp, tref, transferType)),
3754 sRef_showAliasInfo (fref);
3759 /* don't kill shared to suppress future messages */
3760 if (!alkind_isShared (fkind))
3766 /*< yuk! should do this in aliasaux >*/
3768 if (!sRef_isNSLocalVar (tref) && !sRef_sameName (fref, tref))
3772 sRef_setKeptComplete (fref, loc);
3776 sRef_setKept (fref, loc);
3787 if (alkind_isKeep (tkind))
3789 sRef_setKeptComplete (fref, loc);
3793 sRef_killComplete (fref, loc);
3798 if (alkind_isKeep (tkind))
3800 sRef_setKept (fref, loc);
3804 sRef_kill (fref, loc);
3811 else if (alkind_isOwned (tkind))
3813 /* don't kill shared to suppress future messages */
3814 if (!alkind_isShared (fkind))
3817 || !sRef_sameName (fref, tref)) /* result of return parameter */
3823 sRef_setDependentComplete (fref, loc);
3827 sRef_setDependent (fref, loc);
3833 else if (alkind_isShared (tkind))
3835 if (alkind_isFresh (fkind) || alkind_isLocal (fkind))
3839 sRef_setShared (fref, loc);
3843 else if (alkind_isUnknown (tkind) && context_getFlag (FLG_MEMIMPLICIT))
3845 if (alkind_isDependent (fkind))
3847 if (!exprNode_isNullValue (fexp)
3848 && ctype_isMutable (exprNode_getType (fexp))
3849 && (!iseitherassign || sRef_isReference (tref)))
3851 if (canLoseReference (fref, loc))
3858 (FLG_DEPENDENTTRANS,
3859 message ("%s storage %q%q: %q",
3860 alkind_capName (fkind),
3861 sRef_unparseOpt (fref),
3862 transferErrorMessage (transferType, tkind),
3863 generateText (fexp, texp, tref, transferType)),
3866 DPRINTF (("Here: %s / %s", sRef_unparseFull (fref),
3867 sRef_unparseFull (tref)));
3868 sRef_showAliasInfo (fref);
3874 else if (alkind_isNewRef (tkind))
3878 sRef_killComplete (fref, loc);
3881 else if (alkind_isKillRef (tkind))
3883 if (transferType == TT_FCNRETURN)
3885 if (sRef_isNewRef (fref))
3889 message ("New reference returned as temp reference: %q",
3890 generateText (fexp, texp, tref, transferType)),
3893 sRef_showAliasInfo (fref);
3899 if (sRef_isNewRef (fref))
3901 sRef_killComplete (fref, loc);
3905 if (sRef_isRefCounted (fref)
3906 && sRef_isCvar (fref)
3907 && !sRef_isLocalVar (fref))
3912 ("External reference counted storage released: %q",
3913 generateText (fexp, texp, tref, transferType)),
3916 sRef_showAliasInfo (fref);
3932 checkMetaStateConsistent (/*@exposed@*/ sRef fref, sRef tref,
3933 fileloc loc, /*@unused@*/ transferKind transferType)
3936 ** Checks if it is consistent to leave storage marked as tref in state of fref.
3939 valueTable fvalues = sRef_getValueTable (fref);
3940 valueTable tvalues = sRef_getValueTable (tref);
3942 DPRINTF (("Metastate consistent: %s => %s",
3943 sRef_unparseFull (fref),
3944 sRef_unparseFull (tref)));
3946 if (valueTable_isUndefined (tvalues) || valueTable_isUndefined (fvalues)) {
3947 /* Cannot check without value tables. An error was already detected. */
3948 DPRINTF (("No value table: %s / %s",
3949 bool_unparse (valueTable_isUndefined (tvalues)),
3950 bool_unparse (valueTable_isUndefined (fvalues))));
3954 valueTable_elements (fvalues, fkey, fval) {
3956 metaStateInfo minfo;
3958 DPRINTF (("Transfer: %s", fkey));
3959 tval = valueTable_lookup (tvalues, fkey);
3960 minfo = context_lookupMetaStateInfo (fkey);
3962 if (!stateValue_isDefined (tval))
3964 if (ctype_isUnknown (sRef_getType (fref)))
3966 ; /* Okay, put in default values without knowing type */
3971 DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
3972 sRef_unparseFull (tref),
3978 llassert (metaStateInfo_isDefined (minfo));
3980 if (stateValue_isError (fval) || stateValue_isError (tval))
3984 else if (sRef_isDefinitelyNull (fref)
3985 || usymtab_isDefinitelyNull (fref))
3987 ; /* No errors for null values in state transfers. */
3992 stateCombinationTable sctable = metaStateInfo_getTransferTable (minfo);
3993 cstring msg = cstring_undefined;
3994 int nval = stateCombinationTable_lookup (sctable,
3995 stateValue_getValue (fval),
3996 stateValue_getValue (tval),
3999 if (nval == stateValue_error)
4001 llassert (cstring_isDefined (msg));
4003 if (transferType == TT_LEAVETRANS)
4007 else if (transferType == TT_GLOBRETURN)
4012 ("Function returns with global %q in inconsistent state (%q is %q, should be %q): %q",
4013 sRef_unparse (sRef_getRootBase (fref)),
4014 sRef_unparse (fref),
4015 stateValue_unparseValue (fval, minfo),
4016 stateValue_unparseValue (tval, minfo),
4020 sRef_showMetaStateInfo (fref, fkey);
4023 else if (transferType == TT_GLOBPASS)
4028 ("Function called with global %q in inconsistent state (%q is %q, should be %q): %q",
4029 sRef_unparse (sRef_getRootBase (fref)),
4030 stateValue_unparseValue (fval, minfo),
4031 sRef_unparse (fref),
4032 stateValue_unparseValue (tval, minfo),
4036 sRef_showMetaStateInfo (fref, fkey);
4039 else if (transferType == TT_PARAMRETURN)
4044 ("Function returns with parameter %q in inconsistent state (%q is %q, should be %q): %q",
4045 sRef_unparse (sRef_getRootBase (fref)),
4046 stateValue_unparseValue (fval, minfo),
4047 sRef_unparse (fref),
4048 stateValue_unparseValue (tval, minfo),
4052 sRef_showMetaStateInfo (fref, fkey);
4060 ("Invalid transfer from %q %x to %q (%q): %q",
4061 stateValue_unparseValue (fval, minfo),
4062 sRef_unparse (fref),
4063 stateValue_unparseValue (tval, minfo),
4064 sRef_unparse (tref),
4068 sRef_showMetaStateInfo (fref, fkey);
4074 if (stateValue_getValue (fval) != nval)
4076 stateValue_updateValueLoc (fval, nval, loc);
4081 DPRINTF (("Transfer: %s %s -> %s",
4082 fkey, stateValue_unparse (fval), stateValue_unparse (tval)));
4083 } end_valueTable_elements ;
4087 checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref,
4089 fileloc loc, transferKind /*@i32@*/ transferType)
4091 valueTable fvalues = sRef_getValueTable (fref);
4092 valueTable tvalues = sRef_getValueTable (tref);
4094 DPRINTF (("Metastate transfer: from %s", exprNode_unparse (fexp)));
4096 DPRINTF (("Metastate transfer: %s => %s",
4097 sRef_unparseFull (fref),
4098 sRef_unparseFull (tref)));
4100 if (valueTable_isUndefined (tvalues) || valueTable_isUndefined (fvalues)) {
4101 /* Cannot check without value tables. An error was already detected. */
4102 DPRINTF (("No value table: %s / %s",
4103 bool_unparse (valueTable_isUndefined (tvalues)),
4104 bool_unparse (valueTable_isUndefined (fvalues))));
4108 valueTable_elements (fvalues, fkey, fval) {
4110 metaStateInfo minfo;
4111 stateCombinationTable sctable;
4115 DPRINTF (("Transfer: %s", fkey));
4116 tval = valueTable_lookup (tvalues, fkey);
4117 minfo = context_lookupMetaStateInfo (fkey);
4119 if (!stateValue_isDefined (tval))
4121 if (ctype_isUnknown (sRef_getType (fref)))
4123 ; /* Okay, put in default values without knowing type */
4128 DPRINTF (("Metastate transfer: %s => %s",
4129 exprNode_unparse (fexp), exprNode_unparse (texp)));
4130 DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
4131 sRef_unparseFull (tref),
4137 llassert (metaStateInfo_isDefined (minfo));
4139 if (stateValue_isError (fval))
4143 else if (stateValue_isError (tval))
4145 if (sRef_isLocalVar (tref) && transferType == TT_DOASSIGN)
4147 /* Local assignments just replace state. */
4148 stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
4149 DPRINTF (("Update: %s", stateValue_unparse (tval)));
4151 else if (transferType == TT_FCNRETURN)
4153 ; /* Returning from an unannotated function */
4157 DPRINTF (("Transfer to error: %s / %s", sRef_unparseFull (tref),
4158 transferType_unparse (transferType)));
4163 DPRINTF (("Check: %s / %s / %s / %s", fkey,
4164 metaStateInfo_unparse (minfo),
4165 stateValue_unparse (fval),
4166 stateValue_unparse (tval)));
4168 sctable = metaStateInfo_getTransferTable (minfo);
4169 msg = cstring_undefined;
4171 nval = stateCombinationTable_lookup (sctable,
4172 stateValue_getValue (fval),
4173 stateValue_getValue (tval),
4176 if (transferType == TT_DOASSIGN && sRef_isLocalVar (tref))
4178 /* Local assignments just replace state. */
4179 DPRINTF (("No transfer error assigning to local: %s", msg));
4180 stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
4181 DPRINTF (("Update: %s", stateValue_unparse (tval)));
4185 if (cstring_isDefined (msg))
4187 /*@i32 print extra info for assignments@*/
4192 ("Invalid transfer from %q %x to %q (%s): %q",
4193 stateValue_unparseValue (fval, minfo),
4194 sRef_unparse (fref),
4195 stateValue_unparseValue (tval, minfo),
4197 transferErrorExcerpt (transferType, fexp, texp, fcn)),
4200 sRef_showMetaStateInfo (fref, fkey);
4204 DPRINTF (("Suppressed transfer error: %s", msg));
4209 if (transferType == TT_FCNRETURN)
4212 ** Returning this reference from a function, mark this reference
4213 ** so no lost reference errors are returned.
4216 stateValue_updateValueLoc (fval, stateValue_error, loc);
4218 else if (stateValue_getValue (fval) != nval)
4220 stateValue_updateValueLoc (fval, nval, loc);
4231 DPRINTF (("Transfer: %s %s -> %s",
4232 fkey, stateValue_unparse (fval), stateValue_unparse (tval)));
4233 } end_valueTable_elements ;
4237 ** assigns fexp := tref or passes fexp as a parameter, or returns fexp.
4239 ** For assignments, sets alias and definition state accordingly.
4243 checkTransfer (exprNode fexp, /*@dependent@*/ sRef fref,
4244 exprNode texp, /*@dependent@*/ sRef tref,
4246 fileloc loc, transferKind transferType)
4250 if (context_inProtectVars ())
4255 DPRINTF (("Check transfer: %s => %s",
4256 sRef_unparse (fref),
4257 sRef_unparse (tref)));
4258 DPRINTF (("Check transfer: %s => %s",
4259 exprNode_unparse (fexp),
4260 exprNode_unparse (texp)));
4262 checkMetaStateTransfer (fexp, fref, texp, tref, fcn,
4266 ** for local references, we need to check
4267 ** the transfer for all possible aliases.
4270 if (sRef_isLocalVar (tref) && transferType != TT_DOASSIGN)
4272 sRefSet alias = usymtab_allAliases (tref);
4274 sRefSet_realElements (alias, atref)
4276 sRef abase = sRef_getRootBase (atref);
4278 if (sRef_isKnown (atref)
4279 && !sRef_isLocalVar (abase)
4280 && !sRef_isExternal (abase))
4282 atref = sRef_updateSref (atref);
4284 if (sRef_hasName (atref))
4286 if (!sRef_isNew (atref)
4287 && !sRef_sameName (tref, atref))
4289 context_setAliasAnnote (atref, tref);
4292 checkTransferAux (fexp, fref, TRUE,
4296 context_clearAliasAnnote ();
4299 } end_sRefSet_realElements;
4301 sRefSet_free (alias);
4304 if (sRef_isLocalVar (fref))
4306 sRefSet alias = usymtab_allAliases (fref);
4308 sRefSet_realElements (alias, afref)
4310 sRef abase = sRef_getRootBase (afref);
4312 if (sRef_isKnown (afref)
4313 && !sRef_isLocalVar (abase)
4314 && !sRef_isExternal (abase))
4316 afref = sRef_updateSref (afref);
4318 if (sRef_hasName (afref))
4320 if (!sRef_isNew (afref)
4321 && !sRef_sameName (afref, fref))
4323 context_setAliasAnnote (afref, fref);
4326 checkTransferAux (fexp, afref, FALSE,
4330 context_clearAliasAnnote ();
4333 } end_sRefSet_realElements;
4335 sRefSet_free (alias);
4339 checkTransferAux (fexp, fref, FALSE, texp, tref, FALSE,
4344 static /*@exposed@*/ sRef
4345 dependentReference (sRef sr)
4347 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4349 DPRINTF (("Dependent reference: %s", sRef_unparse (sr)));
4350 DPRINTF (("Aliases: %s", sRefSet_unparse (ab)));
4353 ** If there is a local variable that aliases sr, then there is no
4354 ** error. Make the local an only.
4357 if (!sRefSet_isEmpty (ab))
4359 sRef res = sRef_undefined;
4361 DPRINTF (("Here we are!"));
4364 ** make one an only, others alias it
4367 sRefSet_realElements (ab, current)
4369 if (sRef_isOwned (current))
4374 } end_sRefSet_realElements;
4376 if (sRef_isInvalid (res))
4379 ** evans - 2001-03-24
4380 ** No owned element, just choose one!
4381 ** (Any reason for preference?)
4384 res = sRefSet_choose (ab);
4391 return sRef_undefined;
4394 bool canLoseReference (/*@dependent@*/ sRef sr, fileloc loc)
4396 bool gotone = FALSE;
4397 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4400 ** if there is a local variable that aliases sr, then there is no
4401 ** error. Make the local an only.
4404 if (!sRefSet_isEmpty (ab))
4407 ** make one an only, others alias it
4410 sRefSet_realElements (ab, current)
4412 sRef_setLastReference (current, sr, loc);
4415 } end_sRefSet_realElements;
4423 bool canLoseLocalReference (/*@dependent@*/ sRef sr, fileloc loc)
4425 bool gotone = FALSE;
4426 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4429 ** if there is a local variable that aliases sr, then there is no
4430 ** error. Make the local an only.
4433 if (!sRefSet_isEmpty (ab))
4436 ** make one an only, others alias it
4439 sRefSet_realElements (ab, current)
4441 if (sRef_isRealLocalVar (sRef_getRootBase (current)))
4443 sRef_setLastReference (current, sr, loc);
4447 } end_sRefSet_realElements;