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 fileloc p_loc, transferKind p_transferType);
41 static void checkGlobTrans (uentry p_glob, transferKind p_type);
44 checkCompletelyDefined (exprNode p_fexp, /*@exposed@*/ sRef p_fref, sRef p_ofref,
45 exprNode p_texp, sRef p_tref,
46 bool p_topLevel, bool p_inUnion, bool p_directUnion,
47 fileloc p_loc, transferKind p_transferType, int p_depth,
50 static /*@exposed@*/ sRef dependentReference (sRef p_sr);
51 static bool canLoseLocalReference (/*@dependent@*/ sRef p_sr, fileloc p_loc) ;
54 ** returns the most specific alkind
57 alkind alkind_resolve (alkind a1, alkind a2)
59 if (a1 == AK_UNKNOWN || a1 == AK_ERROR) return a2;
60 if (a2 == AK_UNKNOWN || a2 == AK_ERROR || a2 == AK_LOCAL) return a1;
61 if (a1 == AK_LOCAL) return a2;
69 ** FCNRETURN return fref; tref is return type
70 ** GLOBASSIGN tref = fref;
71 ** FCNPASS call (fref) ; tref is the argument type
75 static /*@only@*/ cstring
76 transferErrorMessage (transferKind transferType, alkind tkind) /*@*/
81 return (message ("returned as %s", alkind_unparse (tkind)));
83 return (message ("assigned to %s", alkind_unparse (tkind)));
85 return (message ("assigned to %s", alkind_unparse (tkind)));
87 return (message ("used as initial value for %s",
88 alkind_unparse (tkind)));
90 return (message ("passed as %s param", alkind_unparse (tkind)));
96 static /*@only@*/ cstring
97 transferErrorExcerpt (transferKind transferType, exprNode fexp, exprNode texp) /*@*/
102 return (message ("return %s", exprNode_unparse (fexp)));
106 return (message ("%s = %s", exprNode_unparse (texp), exprNode_unparse (fexp)));
108 /*@i32 make it so called fcn is known here! */
109 return cstring_copy (exprNode_unparse (fexp));
116 transferErrorExpMessage (transferKind transferType, exkind tkind) /*@*/
118 if (exkind_isUnknown (tkind))
120 switch (transferType)
123 return (cstring_makeLiteral ("returned without qualification"));
126 return (cstring_makeLiteral ("assigned to unqualified reference"));
128 return (cstring_makeLiteral ("passed without qualification"));
130 return (cstring_makeLiteral ("used as initial value for unqualified storage"));
136 switch (transferType)
139 return (message ("returned as %s", exkind_unparse (tkind)));
142 return (message ("assigned to %s", exkind_unparse (tkind)));
144 return (message ("passed as %s param", exkind_unparse (tkind)));
152 static /*@observer@*/ cstring
153 transferNullMessage (transferKind transferType) /*@*/
155 switch (transferType)
158 return (cstring_makeLiteralTemp ("returned as non-null"));
161 return (cstring_makeLiteralTemp ("assigned to non-null"));
163 return (cstring_makeLiteralTemp ("initialized to non-null"));
165 return (cstring_makeLiteralTemp ("passed as non-null param"));
171 static /*@dependent@*/ exprNode atFunction = exprNode_undefined;
172 static int atArgNo = 0;
173 static int atNumArgs = 0;
175 static cstring generateText (exprNode e1, exprNode e2,
176 sRef tref, transferKind tt)
179 if (tt == TT_DOASSIGN || tt == TT_GLOBINIT)
181 return (message ("%s = %s", exprNode_unparse (e2),
182 exprNode_unparse (e1)));
184 else if (tt == TT_FIELDASSIGN)
186 return (message ("%s = %s (field %q)",
187 exprNode_unparse (e2),
188 exprNode_unparse (e1),
189 sRef_unparse (tref)));
191 else if (tt == TT_FCNPASS)
193 return (message ("%s (%s%s%s)",
194 exprNode_unparse (atFunction),
195 (atArgNo == 1 ? cstring_undefined
196 : cstring_makeLiteralTemp ("..., ")),
197 exprNode_unparse (e1),
198 (atArgNo == atNumArgs ? cstring_undefined
199 : cstring_makeLiteralTemp (", ..."))));
203 return (cstring_copy (exprNode_unparse (e1)));
207 static /*@observer@*/ cstring
208 transferType_unparse (transferKind transferType) /*@*/
210 switch (transferType)
213 return (cstring_makeLiteralTemp ("Returned"));
216 return (cstring_makeLiteralTemp ("Assigned"));
218 return (cstring_makeLiteralTemp ("Passed"));
220 return (cstring_makeLiteralTemp ("Initialized"));
222 return (cstring_makeLiteralTemp ("GLOB RETURN!"));
224 return (cstring_makeLiteralTemp ("GLOB PASS!"));
226 return (cstring_makeLiteralTemp ("PARAM RETURN!"));
228 return (cstring_makeLiteralTemp ("LEAVE TRANS!"));
234 static /*@observer@*/ cstring udError (sRef s)
238 return cstring_makeLiteralTemp ("released");
240 else if (sRef_isAllocated (s))
242 return cstring_makeLiteralTemp ("allocated but not defined");
246 return cstring_makeLiteralTemp ("undefined");
251 cstring defExpl (sRef s) /*@*/
253 sRef rb = sRef_getRootBase (s);
255 if (sRef_sameName (rb, s))
257 if (sRef_isAllocated (s))
259 return cstring_makeLiteral (" (allocated only)");
261 return cstring_undefined;
265 return (message (" (%q is %s)", sRef_unparse (s), udError (s)));
271 ** More than just definition checking --- checks for consistent state also!
273 ** Returns TRUE if fref is completely defined.
274 ** if !report, returns TRUE unless error is at the deep level.
278 checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
279 exprNode texp, sRef tref,
280 bool topLevel, bool inUnion, bool directUnion,
281 fileloc loc, transferKind transferType,
282 int depth, bool report)
285 alkind fkind = sRef_getAliasKind (fref);
286 alkind tkind = sRef_getAliasKind (tref);
288 DPRINTF (("Check completely defined: %s [%s] / %s [%s]",
289 exprNode_unparse (fexp), sRef_unparseFull (fref),
290 exprNode_unparse (texp), sRef_unparseFull (tref)));
292 if (depth > MAXDEPTH)
296 ("Check definition limit exceeded, checking %q. "
297 "This either means there is a variable with at least "
298 "%d indirections apparent in the program text, or "
299 "there is a bug in LCLint.",
306 if (!sRef_isKnown (fref))
311 if (sRef_isDead (fref))
313 DPRINTF (("Dead storage to completely defined: %s", sRef_unparseFull (fref)));
316 if (alkind_isStack (fkind))
318 ctype rt = ctype_realType (sRef_getType (tref));
320 if (ctype_isMutable (rt) && !ctype_isSU (rt))
322 if (transferType == TT_PARAMRETURN)
327 ("Stack-allocated storage %qreachable from parameter %q",
328 sRef_unparseOpt (fref),
329 sRef_unparse (ofref)),
332 sRef_showAliasInfo (fref);
335 else if (transferType == TT_GLOBRETURN)
340 ("Stack-allocated storage %qreachable from global %q",
341 sRef_unparseOpt (fref),
342 sRef_unparse (ofref)),
345 sRef_showAliasInfo (fref);
348 else if (transferType == TT_FCNRETURN)
353 ("Stack-allocated storage %qreachable from return value: %s",
354 sRef_unparseOpt (fref),
355 exprNode_unparse (fexp)),
358 sRef_showAliasInfo (fref);
370 DPRINTF (("From: %s ==> %s",
371 sRef_unparseFull (fref),
372 sRef_unparseFull (tref)));
374 checkMetaStateConsistent (fref, tref, loc, transferType);
376 if ((sRef_isObserver (fref) && !sRef_isObserver (tref))
377 || (sRef_isExposed (fref) && !(sRef_isObserver (tref)
378 || sRef_isExposed (tref))))
380 flagcode code = (sRef_isObserver (fref)
381 ? FLG_OBSERVERTRANS : FLG_EXPOSETRANS);
383 if (!sRef_isStateLive (fref))
385 ; /* no error (will be a definition error) */
387 else if (transferType == TT_DOASSIGN
388 || transferType == TT_FIELDASSIGN
389 || transferType == TT_GLOBINIT
390 || transferType == TT_FCNPASS)
394 else if (transferType == TT_PARAMRETURN)
399 ("%s storage %qreachable from %s parameter",
400 exkind_capName (sRef_getExKind (fref)),
401 sRef_unparseOpt (fref),
402 exkind_unparseError (sRef_getExKind (tref))),
405 sRef_showExpInfo (fref);
406 sRef_setExKind (fref, XO_UNKNOWN, loc);
409 else if (transferType == TT_LEAVETRANS)
413 else if (transferType == TT_GLOBINIT)
418 ("%s storage %qreachable from %s initial value",
419 exkind_capName (sRef_getExKind (fref)),
420 sRef_unparseOpt (fref),
421 exkind_unparseError (sRef_getExKind (tref))),
424 sRef_showExpInfo (fref);
425 sRef_setExKind (fref, XO_UNKNOWN, loc);
428 else if (transferType == TT_GLOBRETURN)
433 ("%s storage %qreachable from %s global",
434 exkind_capName (sRef_getExKind (fref)),
435 sRef_unparseOpt (fref),
436 exkind_unparseError (sRef_getExKind (tref))),
439 sRef_showExpInfo (fref);
440 sRef_setExKind (fref, XO_UNKNOWN, loc);
443 else if (transferType == TT_FCNRETURN)
448 ("%s storage %qreachable from %s return value",
449 exkind_capName (sRef_getExKind (fref)),
450 sRef_unparseOpt (fref),
451 exkind_unparseError (sRef_getExKind (tref))),
454 sRef_showExpInfo (fref);
455 sRef_setExKind (fref, XO_UNKNOWN, loc);
460 llcontbug (message ("Transfer type: %s",
461 transferType_unparse (transferType)));
466 ("%s storage %qreachable from %s return value",
467 exkind_capName (sRef_getExKind (fref)),
468 sRef_unparseOpt (fref),
469 exkind_unparseError (sRef_getExKind (tref))),
472 sRef_showExpInfo (fref);
473 sRef_setExKind (fref, XO_UNKNOWN, loc);
479 if (!alkind_compatible (fkind, tkind))
481 if (fkind == AK_UNKNOWN && !sRef_isStateLive (fref))
483 ; /* no error (will be a definition error) */
485 else if (transferType == TT_DOASSIGN)
489 else if (transferType == TT_FCNPASS)
491 if (alkind_isKnown (sRef_getAliasKind (tref)))
496 ("Storage %qreachable from passed parameter "
497 "is %s (should be %s): %s",
498 sRef_unparseOpt (fref),
499 alkind_unparse (sRef_getAliasKind (fref)),
500 alkind_unparse (sRef_getAliasKind (tref)),
501 exprNode_unparse (fexp)),
504 sRef_showAliasInfo (fref);
508 else if (transferType == TT_PARAMRETURN)
510 bool noerror = FALSE;
512 if (alkind_isDependent (sRef_getAliasKind (fref)))
514 if (canLoseLocalReference (fref, loc))
524 ("Storage %qreachable from parameter is %s (should be %s)",
525 sRef_unparseOpt (fref),
526 alkind_unparse (sRef_getAliasKind (fref)),
527 alkind_unparse (sRef_getAliasKind (tref))),
530 sRef_showAliasInfo (fref);
533 else if (transferType == TT_LEAVETRANS)
538 ("Storage %qreachable from temporary reference is %s "
539 "at scope exit (should be %s)",
540 sRef_unparseOpt (fref),
541 alkind_unparse (sRef_getAliasKind (fref)),
542 alkind_unparse (sRef_getAliasKind (tref))),
545 sRef_showAliasInfo (fref);
548 else if (transferType == TT_GLOBRETURN)
553 ("Storage %qreachable from global is %s (should be %s)",
554 sRef_unparseOpt (fref),
555 alkind_unparse (sRef_getAliasKind (fref)),
556 alkind_unparse (sRef_getAliasKind (tref))),
559 sRef_showAliasInfo (fref);
562 else if (transferType == TT_FCNRETURN)
567 ("Storage %qreachable from return value is %s (should be %s)",
568 sRef_unparseOpt (fref),
569 alkind_unparse (sRef_getAliasKind (fref)),
570 alkind_unparse (sRef_getAliasKind (tref))),
573 sRef_showAliasInfo (fref);
576 else if (transferType == TT_GLOBINIT)
581 ("Storage %qreachable from initial value is %s (should be %s)",
582 sRef_unparseOpt (fref),
583 alkind_unparse (sRef_getAliasKind (fref)),
584 alkind_unparse (sRef_getAliasKind (tref))),
587 sRef_showAliasInfo (fref);
592 llcontbug (message ("Transfer type: %s",
593 transferType_unparse (transferType)));
598 ("Storage %qreachable from return value is %s (should be %s)",
599 sRef_unparseOpt (fref),
600 alkind_unparse (sRef_getAliasKind (fref)),
601 alkind_unparse (sRef_getAliasKind (tref))),
604 sRef_showAliasInfo (fref);
609 if (sRef_isDead (fref))
616 if (transferType == TT_PARAMRETURN)
621 ("Released storage %q reachable from parameter at return point",
622 sRef_unparse (fref)),
625 sRef_showStateInfo (fref);
629 else if (transferType == TT_LEAVETRANS)
633 message ("Released storage %q reachable from temporary "
634 "reference at scope exit",
635 sRef_unparse (fref)),
638 sRef_showStateInfo (fref);
642 else if (transferType == TT_GLOBRETURN)
646 message ("Released storage %q reachable from global",
647 sRef_unparse (fref)),
650 sRef_showStateInfo (fref);
654 else if (transferType == TT_FCNPASS)
658 message ("Released storage %q reachable from passed parameter",
659 sRef_unparse (fref)),
662 sRef_showStateInfo (fref);
670 message ("Released storage %q reachable from parameter",
671 sRef_unparse (fref)),
674 sRef_showStateInfo (fref);
682 && sRef_possiblyNull (fref)
683 && !sRef_perhapsNull (tref)
684 && ctype_isRealPointer (sRef_getType (tref))
685 && !usymtab_isGuarded (fref))
687 if (transferType == TT_FCNRETURN)
691 message ("%q storage %qderivable from return value: %s",
692 cstring_capitalize (sRef_nullMessage (fref)),
693 sRef_unparseOpt (fref),
694 exprNode_unparse (fexp)),
697 sRef_showNullInfo (fref);
699 DPRINTF (("fref: %s", sRef_unparseFull (fref)));
700 DPRINTF (("tref: %s", sRef_unparseFull (tref)));
702 sRef_setNullError (fref);
705 else if (transferType == TT_GLOBRETURN || transferType == TT_PARAMRETURN)
710 ("Function returns with %s storage derivable from %q %q",
711 sRef_nullMessage (fref),
712 cstring_makeLiteral ((transferType == TT_GLOBRETURN)
713 ? "global" : "parameter"),
714 sRef_unparse (fref)),
717 sRef_showNullInfo (fref);
718 sRef_setNullError (fref);
721 else if (transferType == TT_GLOBPASS)
725 message ("Function called with %s storage "
726 "derivable from global %q",
727 sRef_nullMessage (fref),
728 sRef_unparse (fref)),
731 sRef_showNullInfo (fref);
732 sRef_setNullError (fref);
735 else if (transferType == TT_FCNPASS)
739 message ("%q storage %qderivable from parameter %q",
740 cstring_capitalize (sRef_nullMessage (fref)),
741 sRef_unparseOpt (fref),
742 generateText (fexp, exprNode_undefined,
743 sRef_undefined, TT_FCNPASS)),
746 DPRINTF (("fref: %s", sRef_unparseFull (fref)));
747 DPRINTF (("tref: %s", sRef_unparseFull (tref)));
748 sRef_showNullInfo (fref);
749 sRef_setNullError (fref);
754 llassert (transferType == TT_DOASSIGN
755 || transferType == TT_GLOBINIT
756 || transferType == TT_LEAVETRANS);
760 if (sRef_isRelDef (tref)
761 || sRef_isPartial (tref)
762 || sRef_isAllocated (tref)
763 || sRef_isStateSpecial (tref))
765 /* should check fref is allocated? */
769 ct = ctype_realType (sRef_getType (fref));
771 DPRINTF (("Here: %s", ctype_unparse (ct)));
773 if (!(sRef_isAnyDefined (fref)
774 || sRef_isPdefined (fref)
775 || sRef_isAllocated (fref)
776 || sRef_isStateUnknown (fref)))
778 if (transferType == TT_GLOBRETURN)
783 message ("Function returns with global %q not "
784 "completely defined%q",
785 sRef_unparse (sRef_getRootBase (fref)),
789 sRef_showStateInfo (fref);
790 sRef_setDefined (fref, loc);
793 else if (transferType == TT_GLOBPASS)
799 ("Function called with global %q not completely defined%q",
800 sRef_unparse (sRef_getRootBase (fref)),
804 sRef_showStateInfo (fref);
805 sRef_setDefined (fref, loc);
808 else if (transferType == TT_PARAMRETURN)
810 if (report && !topLevel
813 message ("Function returns storage %q reachable from parameter not "
814 "completely defined%q",
815 sRef_unparse (ofref),
819 sRef_showStateInfo (fref);
820 sRef_setDefined (fref, loc);
823 else if (transferType == TT_LEAVETRANS)
825 if (report && !topLevel
828 message ("Scope exits with storage %q reachable from "
829 "temporary reference not completely defined%q",
830 sRef_unparse (ofref),
834 sRef_showStateInfo (fref);
835 sRef_setDefined (fref, loc);
840 if (transferType != TT_DOASSIGN
841 && (!(sRef_isNew (fref) || sRef_isType (fref))))
845 DPRINTF (("Here we are: %s", sRef_unparseFull (fref)));
847 if (sRef_isDead (fref))
851 message ("%s storage %qwas released: %q",
852 transferType_unparse (transferType),
853 sRef_unparseOpt (fref),
854 generateText (fexp, texp, tref, transferType)),
857 sRef_showStateInfo (fref);
865 ("%s storage %qnot completely defined%q: %q",
866 transferType_unparse (transferType),
867 sRef_unparseOpt (ofref),
869 generateText (fexp, texp, tref, transferType)),
872 sRef rb = sRef_getRootBase (fref);
873 sRef_showStateInfo (fref);
875 DPRINTF (("fref: %s", sRef_unparseFull (fref)));
876 DPRINTF (("rb: %s", sRef_unparseFull (rb)));
877 sRef_setDefinedComplete (rb, loc);
885 if (sRef_isAllocated (fref) && sRef_isValid (tref)
886 && (transferType == TT_DOASSIGN))
888 sRef_setAllocatedComplete (tref, loc);
897 if (ctype_isUnknown (ct))
901 else if (ctype_isPointer (ct) || ctype_isArray (ct)) /* evans 2001-07-12 added ctype_isArray */
903 ctype tct = ctype_realType (sRef_getType (tref));
905 if (sRef_isStateUnknown (fref))
911 DPRINTF (("Here fref: %s", sRef_unparseFull (fref)));
912 DPRINTF (("Here tref: %s", sRef_unparseFull (tref)));
914 if (ctype_isAP (tct) || ctype_isUnknown (tct))
916 sRef fptr = sRef_constructDeref (fref);
917 sRef tptr = sRef_constructDeref (tref);
919 DPRINTF (("Here tptr: %s", sRef_unparseFull (tptr)));
921 return (checkCompletelyDefined (fexp, fptr, ofref,
923 FALSE, inUnion, FALSE, loc,
924 transferType, depth + 1, report));
932 else if (ctype_isStruct (ct))
934 ctype tct = ctype_realType (sRef_getType (tref));
936 DPRINTF (("Struct defined: %s", ctype_unparse (tct)));
938 if (ctype_match (ct, tct))
941 bool hasOneDefined = FALSE;
942 cstringSList badFields = cstringSList_undefined;
944 if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref))
949 DPRINTF (("Check field: %s", sRef_unparseFull (fref)));
951 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
953 DPRINTF (("Is defined: %s", sRef_unparse (fref)));
955 sRefSet_realElements (sRef_derivedFields (fref), sr)
959 hasOneDefined = TRUE;
961 DPRINTF (("Check derived: %s", sRef_unparseFull (sr)));
963 if (sRef_isField (sr))
965 cstring fieldname = sRef_getField (sr);
966 sRef fldref = sRef_makeField (tref, fieldname);
967 bool shouldCheck = !sRef_isRecursiveField (fldref);
973 (checkCompletelyDefined (fexp, sr, ofref,
975 FALSE, inUnion, FALSE, loc,
976 transferType, depth + 1,
987 badFields = cstringSList_add (badFields,
991 } end_sRefSet_realElements;
993 else if (sRef_isAllocated (fref))
996 ** for structures, each field must be completely defined
999 uentryList fields = ctype_getFields (ct);
1001 uentryList_elements (fields, ue)
1004 cstring name = uentry_getRealName (ue);
1005 sRef ffield = sRef_makeField (fref, name);
1006 sRef tfield = sRef_makeField (tref, name);
1007 bool shouldCheck = !sRef_isRecursiveField (tfield);
1015 thisField = ynm_toBoolRelaxed
1016 (checkCompletelyDefined (fexp, ffield, ofref,
1018 FALSE, inUnion, FALSE,
1026 badFields = cstringSList_add (badFields, uentry_rawName (ue));
1030 hasOneDefined = TRUE;
1032 } end_uentryList_elements;
1036 DPRINTF (("Not checking: %s", sRef_unparseFull (fref)));
1039 if (!isOk && (!inUnion || hasOneDefined))
1041 if (transferType == TT_GLOBRETURN)
1045 message ("Global storage %q contains %d undefined field%& "
1046 "when call returns: %q",
1047 sRef_unparse (fref),
1048 cstringSList_size (badFields),
1049 cstringSList_unparseAbbrev (badFields)),
1052 sRef_setDefined (fref, loc);
1055 else if (transferType == TT_GLOBPASS)
1059 message ("Global storage %q contains %d undefined field%& "
1061 sRef_unparse (fref),
1062 cstringSList_size (badFields),
1063 cstringSList_unparseAbbrev (badFields)),
1066 sRef_setDefined (fref, loc);
1069 else if (transferType == TT_PARAMRETURN)
1073 message ("Storage %qreachable from parameter "
1074 "contains %d undefined field%&: %q",
1075 sRef_unparseOpt (fref),
1076 cstringSList_size (badFields),
1077 cstringSList_unparseAbbrev (badFields)),
1080 sRef_setDefined (fref, loc);
1083 else if (transferType == TT_LEAVETRANS)
1091 message ("%s storage %qcontains %d undefined field%&: %q",
1092 transferType_unparse (transferType),
1093 sRef_unparseOpt (fref),
1094 cstringSList_size (badFields),
1095 cstringSList_unparseAbbrev (badFields)),
1098 sRef_setDefined (fref, loc);
1103 cstringSList_free (badFields);
1109 return (ynm_fromBool (hasOneDefined));
1118 return (ynm_fromBool (!report || isOk));
1126 else if (ctype_isUnion (ct))
1128 if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref))
1134 ctype tct = ctype_realType (sRef_getType (tref));
1136 if (ctype_isKnown (tct) && ctype_match (ct, tct))
1138 cstringSList goodFields = cstringSList_new ();
1140 int nelements = sRefSet_size (sRef_derivedFields (fref));
1143 ** for unions, at least one field must be completely defined
1146 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
1151 sRefSet_realElements (sRef_derivedFields (fref), sr)
1155 if (sRef_isField (sr))
1157 sRef fldref = sRef_makeField (tref, sRef_getField (sr));
1159 DPRINTF (("Trying union field: %s", sRef_unparseFull (fldref)));
1161 thisField = ynm_toBoolStrict
1162 (checkCompletelyDefined
1164 texp, fldref, FALSE, inUnion,
1165 (nelements > 1 ? TRUE : FALSE),
1166 loc, transferType, depth + 1, FALSE));
1170 goodFields = cstringSList_add
1171 (goodFields, sRef_getField (sr));
1174 } end_sRefSet_realElements;
1176 if (cstringSList_empty (goodFields)
1178 && context_getFlag (FLG_UNIONDEF))
1182 if (transferType == TT_PARAMRETURN)
1186 message ("Union %q reachable from parameter has "
1188 sRef_unparse (fref)),
1191 else if (transferType == TT_LEAVETRANS)
1195 message ("Union %q has no defined field at scope exit",
1196 sRef_unparse (fref)),
1199 else if (transferType == TT_DOASSIGN
1200 || transferType == TT_FIELDASSIGN
1201 || transferType == TT_GLOBINIT)
1209 message ("%s union %q has no defined field",
1210 transferType_unparse (transferType),
1211 sRef_unparse (fref)),
1218 cstringSList_free (goodFields);
1219 return ynm_fromBool (!report || isOk);
1232 ** fref is being free'd
1236 DSC_GLOB, DSC_LOCAL, DSC_PARAM, DSC_STRUCT
1239 static /*@observer@*/ cstring dscCode_unparse (dscCode desc) /*@*/
1244 return cstring_makeLiteralTemp ("killed global");
1246 return cstring_makeLiteralTemp ("variable declared in this scope");
1248 return cstring_makeLiteralTemp ("released storage");
1250 return cstring_makeLiteralTemp ("released structure parameter");
1257 checkCompletelyDestroyed (exprNode p_fexp, sRef p_fref, bool p_topLevel,
1258 fileloc p_loc, int p_depth, dscCode p_desc,
1261 bool checkGlobalDestroyed (sRef fref, fileloc loc)
1263 return (checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1264 loc, 0, DSC_GLOB, FALSE));
1267 void checkLocalDestroyed (sRef fref, fileloc loc)
1269 if (sRef_isObserver (fref) || sRef_isExposed (fref)
1270 || sRef_isPartial (fref))
1276 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1277 loc, 0, DSC_LOCAL, FALSE);
1281 void checkStructDestroyed (sRef fref, fileloc loc)
1283 DPRINTF (("Check struct destroyed: %s", sRef_unparse (fref)));
1285 if (sRef_isObserver (fref) || sRef_isExposed (fref)
1286 || sRef_isPartial (fref))
1288 DPRINTF (("Its exposed!"));;
1292 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1293 loc, 0, DSC_STRUCT, FALSE);
1298 checkCompletelyDestroyed (exprNode fexp, sRef fref, bool topLevel,
1299 fileloc loc, int depth,
1300 dscCode desc, bool hideErrors)
1304 DPRINTF (("Check completely destroyed: %s", sRef_unparseFull (fref)));
1306 if (depth > MAXDEPTH)
1308 llquietbug (message ("checkCompletelyDestroyed: too deep: %s / %q",
1309 exprNode_unparse (fexp),
1310 sRef_unparseFull (fref)));
1314 if (!sRef_isKnown (fref)) return TRUE;
1316 /* evans 2001-03-24: added this. Definitely null values are always destroyed. */
1318 if (sRef_isDefinitelyNull (fref))
1323 if (sRef_isDependent (fref) || sRef_isShared (fref) || sRef_isKept (fref))
1330 ** evans 2001-03-24: if there is a dependent reference to this storage,
1331 ** no need to destroy, but make it responsible.
1334 sRef depRef = dependentReference (fref);
1336 DPRINTF (("Destroyed? %s / %s",
1337 sRef_unparseFull (fref),
1338 sRef_unparseFull (depRef)));
1340 DPRINTF (("Aliases: %s", usymtab_unparseAliases ()));
1342 if (sRef_isValid (depRef))
1345 ** If the referenced storage was not dependent, we make
1346 ** the reference the owner since it must eventually be
1350 if (!sRef_isDependent (depRef))
1352 sRef_setOnly (depRef, loc); /* could be owned? */
1355 sRef_kill (fref, loc);
1360 if (sRef_isPdefined (fref) && !context_getFlag (FLG_STRICTDESTROY))
1362 DPRINTF (("Partial: %s", sRef_unparseFull (fref)));
1363 hideErrors = TRUE; /* Don't report any more errors, but still change ownership. */
1366 if (usymtab_isDefinitelyNull (fref))
1368 DPRINTF (("Probably null!"));
1372 if (!context_getFlag (FLG_COMPDESTROY)) return TRUE;
1373 if (!context_getFlag (FLG_MUSTFREE)) return TRUE;
1375 ct = ctype_realType (sRef_getType (fref));
1377 DPRINTF (("Here: %s", ctype_unparse (ct)));
1381 bool docheck = FALSE;
1384 if (sRef_isFresh (fref) || sRef_isOnly (fref))
1388 DPRINTF (("Here: %s", ctype_unparse (ct)));
1389 if (sRef_isDead (fref)
1390 || sRef_isUnuseable (fref)
1391 || sRef_definitelyNull (fref)
1392 || sRef_isObserver (fref)
1393 || sRef_isExposed (fref))
1401 if (sRef_isPossiblyDead (fref) || sRef_isRelDef (fref))
1403 if (exprNode_isDefined (fexp))
1409 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1410 message ("Only storage %q (type %s) derived from %s "
1411 "may not have been released: %s",
1412 sRef_unparse (fref),
1413 ctype_unparse (sRef_getType (fref)),
1414 dscCode_unparse (desc),
1415 exprNode_unparse (fexp)),
1424 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1426 ("Only storage %q (type %s) derived from %s "
1427 "may not have been released",
1428 sRef_unparse (fref),
1429 ctype_unparse (sRef_getType (fref)),
1430 dscCode_unparse (desc)),
1436 sRef_kill (fref, loc); /* prevent further errors */
1441 if (sRef_isStateUndefined (fref))
1443 DPRINTF (("Here: %s", ctype_unparse (ct)));
1448 if (exprNode_isDefined (fexp))
1450 DPRINTF (("Here: %s", sRef_unparseFull (fref)));
1457 message ("Only storage %q (type %s) derived from %s "
1458 "is not released (memory leak): %s",
1459 sRef_unparse (fref),
1460 ctype_unparse (sRef_getType (fref)),
1461 dscCode_unparse (desc),
1462 exprNode_unparse (fexp)),
1472 message ("Only storage %q (type %s) derived from %s "
1473 "is not released (memory leak)",
1474 sRef_unparse (fref),
1475 ctype_unparse (sRef_getType (fref)),
1476 dscCode_unparse (desc)),
1484 /* sRef_kill (fref, loc); */ /* prevent further errors */
1485 DPRINTF (("Killed: %s", sRef_unparseFull (fref)));
1490 DPRINTF (("Here: %s", ctype_unparse (ct)));
1494 if (/*! evs-2001-03-24 sRef_isAnyDefined (fref) || */
1496 || (sRef_isPdefined (fref)
1497 && sRefSet_isEmpty (sRef_derivedFields (fref))))
1499 DPRINTF (("Here: %s [%s / %s]",
1500 sRef_unparseFull (fref),
1501 bool_unparse (sRef_isAnyDefined (fref)),
1502 bool_unparse (sRef_isDead (fref))));
1507 DPRINTF (("Here..."));
1509 if (ctype_isPointer (ct))
1511 sRef fptr = sRef_constructDeadDeref (fref);
1514 res = checkCompletelyDestroyed (fexp, fptr, FALSE, loc,
1515 depth + 1, desc, hideErrors);
1519 else if (ctype_isArray (ct))
1521 if ((sRef_isStateUnknown (fref) || sRef_isAllocated (fref))
1522 && !sRef_hasDerived (fref))
1525 ** Bogosity necessary to prevent infinite depth.
1532 sRef farr = sRef_constructDeadDeref (fref);
1534 return (checkCompletelyDestroyed (fexp, farr, FALSE, loc,
1535 depth + 1, desc, hideErrors));
1538 else if (ctype_isStruct (ct))
1541 ** for structures, each field must be completely destroyed
1545 uentryList fields = ctype_getFields (ct);
1547 DPRINTF (("Struct fields: %s", uentryList_unparse (fields)));
1549 if (depth >= MAXDEPTH)
1551 llquietbug (message ("checkCompletelyDestroyed (fields): too deep: %s / %q",
1552 exprNode_unparse (fexp),
1553 sRef_unparseFull (fref)));
1559 uentryList_elements (fields, ue)
1561 sRef field = sRef_makeField (fref, uentry_rawName (ue));
1564 ** note order of && operands --- want to report multiple errors
1567 DPRINTF (("Check field: %s", sRef_unparseFull (field)));
1569 isOk = (checkCompletelyDestroyed (fexp, field, FALSE, loc,
1570 depth + 1, desc, hideErrors)
1572 } end_uentryList_elements;
1584 checkReturnTransfer (exprNode fexp, uentry rval)
1586 sRef uref = uentry_getSref (rval);
1587 sRef rref = sRef_makeNew (sRef_getType (uref), uref, cstring_undefined);
1588 uentry fcn = context_getHeader ();
1589 sRef fref = exprNode_getSref (fexp);
1590 stateClauseList clauses = uentry_getStateClauseList (fcn);
1592 DPRINTF (("Check return: %s as %s = %s",
1593 exprNode_unparse (fexp),
1594 sRef_unparseFull (uref),
1595 sRef_unparseFull (rref)));
1597 /* evans 2001-07-18: removed: if (sRef_isStateSpecial (rref)) */
1599 DPRINTF (("Check state clauses: %s",
1600 stateClauseList_unparse (clauses)));
1602 stateClauseList_postElements (clauses, cl)
1604 if (stateClause_isGlobal (cl))
1608 else if (stateClause_setsMetaState (cl))
1610 sRefSet refs = stateClause_getRefs (cl);
1611 qual ql = stateClause_getMetaQual (cl);
1612 annotationInfo ainfo = qual_getAnnotationInfo (ql);
1613 metaStateInfo minfo = annotationInfo_getState (ainfo);
1614 cstring key = metaStateInfo_getName (minfo);
1615 int mvalue = annotationInfo_getValue (ainfo);
1617 DPRINTF (("Return check: %s", stateClause_unparse (cl)));
1619 sRefSet_elements (refs, el)
1621 sRef base = sRef_getRootBase (el);
1623 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
1625 if (sRef_isResult (base))
1627 sRef sr = sRef_fixBase (el, fref);
1629 if (!sRef_checkMetaStateValue (sr, key, mvalue))
1633 message ("Result state %q does not satisfy ensures "
1634 "clause: %q (state is %q, should be %s): %s",
1636 stateClause_unparse (cl),
1637 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
1639 metaStateInfo_unparseValue (minfo, mvalue),
1640 exprNode_unparse (fexp)),
1641 exprNode_loc (fexp)))
1643 sRef_showAliasInfo (sr);
1651 ** Non-results are checked in exit scope.
1654 } end_sRefSet_elements ;
1658 sRefSet refs = stateClause_getRefs (cl);
1659 sRefTest tst = stateClause_getPostTestFunction (cl);
1660 sRefMod modf = stateClause_getReturnEffectFunction (cl);
1662 DPRINTF (("Clause: %s / %s",
1663 stateClause_unparse (cl),
1664 sRefSet_unparse (refs)));
1666 sRefSet_elements (refs, el)
1668 sRef base = sRef_getRootBase (el);
1670 DPRINTF (("el: %s / %s", sRef_unparse (el),
1671 sRef_unparse (base)));
1673 if (sRef_isResult (base))
1675 sRef sr = sRef_fixBase (el, fref);
1677 if (tst != NULL && !(tst (sr)))
1680 (stateClause_postErrorCode (cl),
1681 message ("%s storage %q corresponds to "
1682 "storage %q listed in %q clause: %s",
1683 stateClause_postErrorString (cl, sr),
1686 stateClause_unparseKind (cl),
1687 exprNode_unparse (fexp)),
1688 exprNode_loc (fexp)))
1690 sRefShower ss = stateClause_getPostTestShower (cl);
1701 modf (sr, exprNode_loc (fexp));
1707 ** Non-results are checked in exit scope.
1710 } end_sRefSet_elements ;
1712 } end_stateClauseList_postElements ;
1714 if (ctype_isRealSU (exprNode_getType (fexp)))
1716 sRef ffref = exprNode_getSref (fexp);
1718 checkStructTransfer (exprNode_undefined, rref,
1720 exprNode_loc (fexp),
1725 (void) checkTransfer (fexp, exprNode_getSref (fexp),
1726 exprNode_undefined, rref,
1727 exprNode_loc (fexp), TT_FCNRETURN);
1732 checkPassstateClauseList (uentry ue, exprNode fexp, sRef fref, int argno)
1734 stateClauseList clauses = uentry_getStateClauseList (ue);
1736 DPRINTF (("Check pass special: %s / %s",
1737 exprNode_unparse (fexp), sRef_unparseFull (fref)));
1739 stateClauseList_preElements (clauses, cl)
1741 if (stateClause_isGlobal (cl))
1747 sRefSet refs = stateClause_getRefs (cl);
1748 sRefTest tst = stateClause_getPreTestFunction (cl);
1749 sRefMod modf = stateClause_getEffectFunction (cl);
1751 sRefSet_elements (refs, el)
1753 sRef base = sRef_getRootBase (el);
1755 if (sRef_isResult (base))
1757 ; /* nothing to check before */
1759 else if (sRef_isParam (base))
1761 if (sRef_getParam (base) == argno - 1)
1765 DPRINTF (("Fix base: %s / %s",
1766 sRef_unparseFull (el),
1767 sRef_unparseFull (fref)));
1769 sb = sRef_fixBase (el, fref);
1771 if (tst != NULL && !(tst(sb)))
1774 (stateClause_preErrorCode (cl),
1775 message ("%s storage %qcorresponds to "
1776 "storage listed in %q clause of "
1777 "called function: %s",
1778 stateClause_preErrorString (cl, sb),
1779 sRef_unparseOpt (sb),
1780 stateClause_unparseKind (cl),
1781 exprNode_unparse (fexp)),
1782 exprNode_loc (fexp));
1787 DPRINTF (("Fixing: %s", sRef_unparseFull (sb)));
1788 modf (sb, exprNode_loc (fexp));
1789 DPRINTF (("==> %s", sRef_unparseFull (sb)));
1797 } end_sRefSet_elements ;
1799 } end_stateClauseList_preElements ;
1801 DPRINTF (("After: %s", sRef_unparseFull (fref)));
1805 ** should not modify arg
1809 checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
1810 /*@dependent@*/ exprNode fcn, int argno, int totargs)
1812 sRef tref = uentry_getSref (arg);
1813 sRef fref = exprNode_getSref (fexp);
1815 bool isPartial = FALSE;
1816 bool isImpOut = FALSE;
1817 ctype ct = uentry_getType (arg);
1819 DPRINTF (("Check pass: %s -> %s",
1820 sRef_unparseFull (fref),
1821 sRef_unparseFull (tref)));
1825 atNumArgs = totargs;
1827 if (ctype_isElips (ct))
1832 DPRINTF (("Out arg: %s", bool_unparse (uentry_isOut (arg))));
1834 if (!ctype_isElips (ct) &&
1835 (ctype_isVoidPointer (ct) && uentry_isOut (arg) && sRef_isOnly (tref)))
1837 if (ctype_isRealAP (ct))
1839 if (sRef_aliasCheckSimplePred (sRef_isDead, fref))
1843 message ("Dead storage %qpassed as out parameter to %s: %s",
1844 sRef_unparseOpt (fref),
1845 exprNode_unparse (fcn),
1846 exprNode_unparse (fexp)),
1847 exprNode_loc (fexp)))
1849 if (sRef_isDead (fref))
1851 sRef_showStateInfo (fref);
1855 DPRINTF (("Not really dead!"));
1856 sRef_showStateInfo (fref);
1860 sRef_setAllocated (fref, exprNode_loc (fexp));
1862 else if (context_getFlag (FLG_STRICTUSERELEASED)
1863 && sRef_aliasCheckSimplePred (sRef_isPossiblyDead, fref))
1866 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1867 message ("Possibly dead storage %qpassed as out parameter: %s",
1868 sRef_unparseOpt (fref),
1869 exprNode_unparse (fexp)),
1870 exprNode_loc (fexp)))
1872 if (sRef_isPossiblyDead (fref))
1874 sRef_showStateInfo (fref);
1878 sRef_setAllocated (fref, exprNode_loc (fexp));
1880 else if (sRef_aliasCheckSimplePred (sRef_isStateUndefined, fref)
1881 || sRef_aliasCheckSimplePred (sRef_isUnuseable, fref))
1885 message ("Unallocated storage %qpassed as out parameter: %s",
1886 sRef_unparseOpt (fref),
1887 exprNode_unparse (fexp)),
1888 exprNode_loc (fexp));
1890 sRef_setAllocated (fref, exprNode_loc (fexp));
1898 (void) checkCompletelyDestroyed (fexp, fref, TRUE, exprNode_loc (fexp),
1899 0, DSC_PARAM, FALSE);
1901 /* make it defined now, so checkTransfer is okay */
1902 sRef_setDefined (fref, exprNode_loc (fexp));
1904 else if (uentry_isOut (arg))
1906 DPRINTF (("Here we are!"));
1908 if (ctype_isRealAP (ct)
1909 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1913 message ("Unallocated storage %qpassed as out parameter to %s: %s",
1914 sRef_unparseOpt (fref),
1915 exprNode_unparse (fcn),
1916 exprNode_unparse (fexp)),
1917 exprNode_loc (fexp));
1918 sRef_setAllocated (fref, exprNode_loc (fexp));
1920 else if (sRef_isDead (fref))
1924 message ("Dead storage %qpassed as out parameter to %s: %s",
1925 sRef_unparseOpt (fref),
1926 exprNode_unparse (fcn),
1927 exprNode_unparse (fexp)),
1928 exprNode_loc (fexp)))
1930 sRef_showStateInfo (fref);
1931 sRef_setAllocated (fref, exprNode_loc (fexp));
1934 else if (sRef_isPossiblyDead (fref))
1937 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1938 message ("Possibly dead storage %qpassed as out parameter to %s: %s",
1939 sRef_unparseOpt (fref),
1940 exprNode_unparse (fcn),
1941 exprNode_unparse (fexp)),
1942 exprNode_loc (fexp)))
1944 sRef_showStateInfo (fref);
1945 sRef_setAllocated (fref, exprNode_loc (fexp));
1955 else if (uentry_isPartial (arg))
1957 if (ctype_isRealAP (ct)
1958 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1962 message ("Unallocated storage %qpassed as partial parameter: %s",
1963 sRef_unparseOpt (fref),
1964 exprNode_unparse (fexp)),
1965 exprNode_loc (fexp));
1966 sRef_setAllocated (fref, exprNode_loc (fexp));
1968 else if (sRef_isDead (fref))
1972 message ("Dead storage %qpassed as partial parameter to %s: %s",
1973 sRef_unparseOpt (fref),
1974 exprNode_unparse (fcn),
1975 exprNode_unparse (fexp)),
1976 exprNode_loc (fexp)))
1978 sRef_showStateInfo (fref);
1979 sRef_setAllocated (fref, exprNode_loc (fexp));
1982 else if (sRef_isPossiblyDead (fref))
1985 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1986 message ("Possibly dead storage %qpassed as partial parameter to %s: %s",
1987 sRef_unparseOpt (fref),
1988 exprNode_unparse (fcn),
1989 exprNode_unparse (fexp)),
1990 exprNode_loc (fexp)))
1992 sRef_showStateInfo (fref);
1993 sRef_setAllocated (fref, exprNode_loc (fexp));
2003 else if (uentry_isStateSpecial (arg))
2005 uentry ue = exprNode_getUentry (fcn);
2007 if (ctype_isRealAP (ct)
2008 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
2012 message ("Unallocated storage %qpassed as special parameter: %s",
2013 sRef_unparseOpt (fref),
2014 exprNode_unparse (fexp)),
2015 exprNode_loc (fexp));
2016 sRef_setAllocated (fref, exprNode_loc (fexp));
2018 else if (sRef_isDead (fref))
2022 message ("Dead storage %qpassed as special parameter to %s: %s",
2023 sRef_unparseOpt (fref),
2024 exprNode_unparse (fcn),
2025 exprNode_unparse (fexp)),
2026 exprNode_loc (fexp)))
2028 sRef_showStateInfo (fref);
2029 sRef_setAllocated (fref, exprNode_loc (fexp));
2032 else if (sRef_isPossiblyDead (fref))
2035 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
2036 message ("Possibly dead storage %qpassed as special parameter to %s: %s",
2037 sRef_unparseOpt (fref),
2038 exprNode_unparse (fcn),
2039 exprNode_unparse (fexp)),
2040 exprNode_loc (fexp)))
2042 sRef_showStateInfo (fref);
2043 sRef_setAllocated (fref, exprNode_loc (fexp));
2051 if (uentry_hasStateClauseList (ue))
2053 checkPassstateClauseList (ue, fexp, fref, argno);
2058 else if (sRef_isStateDefined (tref))
2060 exprNode_checkUseParam (fexp);
2064 if (isSpec || (!context_getFlag (FLG_IMPOUTS)))
2066 exprNode_checkUseParam (fexp);
2070 if (!sRef_isMacroParamRef (fref)
2071 && (ctype_isRealAP (ct)))
2073 if (sRef_isAddress (fref))
2075 if (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref))
2080 ("Unallocated address %qpassed as implicit "
2081 "out parameter: %s",
2082 sRef_unparseOpt (fref),
2083 exprNode_unparse (fexp)),
2084 exprNode_loc (fexp));
2085 sRef_setAllocated (fref, exprNode_loc (fexp));
2089 /* yes, I really mean this! */
2090 tref = sRef_copy (tref);
2091 sRef_setAllocated (tref, exprNode_loc (fexp));
2098 exprNode_checkUseParam (fexp);
2103 if (sRef_isNew (fref))
2105 alkind tkind = sRef_getAliasKind (tref);
2107 if ((sRef_isFresh (fref) || sRef_isOnly (fref))
2108 && !alkind_isOnly (tkind)
2109 && !alkind_isKeep (tkind)
2110 && !alkind_isOwned (tkind)
2111 && !alkind_isError (tkind)
2112 && !uentry_isReturned (arg))
2117 message ("New fresh storage %q(type %s) passed as %s (not released): %s",
2118 sRef_unparseOpt (fref),
2119 ctype_unparse (sRef_getType (fref)),
2120 alkind_unparse (sRef_getAliasKind (tref)),
2121 exprNode_unparse (fexp)),
2122 exprNode_loc (fexp));
2123 DPRINTF (("Fresh: %s", sRef_unparseFull (fref)));
2127 if (sRef_isNewRef (fref) && !sRef_isKillRef (tref))
2129 alkind ak = sRef_getAliasKind (tref);
2131 if (!alkind_isError (ak))
2135 message ("New reference %q(type %s) passed as %s (not released): %s",
2136 sRef_unparseOpt (fref),
2137 ctype_unparse (sRef_getType (fref)),
2138 alkind_unparse (sRef_getAliasKind (tref)),
2139 exprNode_unparse (fexp)),
2140 exprNode_loc (fexp));
2146 (void) checkTransfer (fexp, exprNode_getSref (fexp),
2147 exprNode_undefined, tref,
2148 exprNode_loc (fexp), TT_FCNPASS);
2151 fref = exprNode_getSref (fexp);
2153 if (isOut && !sRef_isDead (fref) && !sRef_isPossiblyDead (fref))
2157 if (ctype_isRealAP (sRef_getType (fref)))
2159 base = sRef_makePointer (fref);
2168 exprNode_checkMSet (fexp, base);
2172 exprNode_checkSet (fexp, base);
2175 if (sRef_isValid (base))
2179 sRef_clearDerived (base);
2180 sRef_setDefined (base, exprNode_loc (fexp));
2181 usymtab_clearAlias (base);
2182 sRef_setNullUnknown (base, exprNode_loc (fexp));
2188 if (sRef_isValid (fref))
2190 sRef_setPartial (fref, exprNode_loc (fexp));
2194 atFunction = exprNode_undefined;
2198 /* need to fixup here: derived refs could be bogus */
2199 /* (better to change sRef to not add derivs for "protected" ref) */
2201 uentry_fixupSref (arg);
2205 DPRINTF (("Check pass: ==> %s",
2206 sRef_unparseFull (fref)));
2210 checkGlobReturn (uentry glob)
2212 sRef_protectDerivs ();
2213 checkGlobTrans (glob, TT_GLOBRETURN);
2214 sRef_clearProtectDerivs ();
2217 void checkParamReturn (uentry actual)
2219 checkLeaveTrans (actual, TT_PARAMRETURN);
2222 void checkLoseRef (uentry actual)
2224 checkLeaveTrans (actual, TT_LEAVETRANS);
2228 checkLeaveTrans (uentry actual, transferKind transferType)
2230 sRef aref = uentry_getSref (actual);
2231 sRef origref = uentry_getOrigSref (actual);
2233 if (transferType == TT_PARAMRETURN
2234 && (sRef_isKeep (origref) || sRef_isOnly (origref)
2235 || sRef_isOwned (origref)))
2237 /* caller cannot use, nothing to check */
2241 if (sRef_isNSLocalVar (origref))
2247 DPRINTF (("Leave trans: %s", uentry_unparseFull (actual)));
2249 (void) checkCompletelyDefined (exprNode_undefined, aref, aref,
2250 exprNode_undefined, origref,
2252 g_currentloc, transferType,
2259 checkGlobTrans (uentry glob, transferKind type)
2261 sRef eref = uentry_getOrigSref (glob);
2263 (void) checkCompletelyDefined (exprNode_undefined, uentry_getSref (glob), uentry_getSref (glob),
2264 exprNode_undefined, eref,
2266 g_currentloc, type, 0, TRUE);
2270 ** For lhs of assignment, alias kind is set from basic type.
2275 fixAssignLhs (sRef s)
2277 sRef_resetStateComplete (s);
2280 static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srhs,
2284 ctype st = ctype_realType (sRef_getType (srhs));
2286 if (ctype_isSU (st) && ctype_isRealSU (sRef_getType (slhs))
2287 && ctype_match (sRef_getType (slhs), st))
2289 if (tt == TT_DOASSIGN && sRef_isStateDefined (srhs))
2291 sRef_setDefinedComplete (slhs, loc);
2294 if (sRef_isDependent (slhs)
2295 || sRef_isObserver (slhs)
2296 || sRef_isExposed (slhs))
2302 if (sRef_isLocalVar (slhs)
2303 && sRef_isFileOrGlobalScope (sRef_getRootBase (srhs)))
2305 sRef_setDependent (slhs, exprNode_loc (lhs));
2309 if (ctype_isUnion (st))
2311 sRef_setDefState (slhs, sRef_getDefState (srhs),
2312 exprNode_loc (lhs));
2314 sRefSet_realElements (sRef_derivedFields (srhs), sr)
2316 if (sRef_isField (sr))
2318 cstring fieldname = sRef_getField (sr);
2319 sRef lfld = sRef_makeField (slhs, fieldname);
2321 (void) checkTransfer (rhs, sr, lhs, lfld,
2322 exprNode_loc (lhs), tt);
2324 } end_sRefSet_realElements ;
2328 uentryList fields = ctype_getFields (st);
2330 uentryList_elements (fields, field)
2332 sRef rfld = sRef_makeField (srhs, uentry_rawName (field));
2333 sRef lfld = sRef_makeField (slhs, uentry_rawName (field));
2334 (void) checkTransfer (rhs, rfld, lhs, lfld, exprNode_loc (lhs), tt);
2335 } end_uentryList_elements ;
2338 if (sRef_isOnly (srhs))
2340 sRef_setKeptComplete (srhs, loc);
2348 checkInitTransfer (exprNode lhs, exprNode rhs)
2350 sRef slhs = exprNode_getSref (lhs);
2352 if (sRef_isFileOrGlobalScope (slhs) || (!sRef_isCvar (slhs)))
2354 (void) checkTransfer (rhs, exprNode_getSref (rhs),
2355 lhs, slhs, exprNode_loc (rhs), TT_GLOBINIT);
2359 checkAssignTransfer (lhs, rhs);
2364 checkAssignTransfer (exprNode lhs, exprNode rhs)
2366 sRef slhs = exprNode_getSref (lhs);
2367 sRef srhs = exprNode_getSref (rhs);
2368 sRef base = sRef_getBaseSafe (slhs);
2371 DPRINTF (("Check assign: %s = %s", exprNode_unparse (lhs),
2372 exprNode_unparse (rhs)));
2373 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2374 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2376 if (ctype_isRealSU (sRef_getType (srhs)))
2378 checkStructTransfer (lhs, slhs, rhs, srhs, exprNode_loc (lhs), TT_FIELDASSIGN);
2382 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2383 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2384 (void) checkTransfer (rhs, srhs, lhs, slhs,
2385 exprNode_loc (lhs), TT_DOASSIGN);
2386 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2387 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2390 if (sRef_isConst (srhs) && sRef_isLocalState (srhs))
2392 /* constants can match anything (e.g., NULL) */
2393 sRef_setAliasKind (slhs, AK_ERROR, fileloc_undefined);
2396 if (sRef_isValid (base) && sRef_isStateDefined (base))
2398 sRef_setPdefined (base, g_currentloc);
2401 if (sRef_isPartial (srhs))
2403 sRef_setPartial (slhs, exprNode_loc (rhs));
2406 ns = sRef_getNullState (srhs);
2408 if (nstate_possiblyNull (ns))
2410 if (usymtab_isGuarded (srhs))
2416 sRef_setNullStateInnerComplete (slhs, ns, exprNode_loc (rhs));
2418 if (sRef_isExposed (srhs) || sRef_isObserver (srhs))
2420 sRef_setExKind (slhs, sRef_getExKind (srhs), exprNode_loc (rhs));
2423 DPRINTF (("Done transfer: %s", sRef_unparseFull (slhs)));
2427 checkTransferNullAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2428 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2429 fileloc loc, transferKind transferType)
2431 alkind tkind = sRef_getAliasKind (tref);
2432 ctype ttyp = ctype_realType (sRef_getType (tref));
2434 if (ctype_isUnknown (ttyp))
2436 ttyp = exprNode_getType (texp);
2438 if (ctype_isUnknown (ttyp))
2440 ttyp = exprNode_getType (fexp);
2442 if (ctype_isUnknown (ttyp))
2444 ttyp = sRef_getType (fref);
2449 if (ctype_isFunction (ttyp) && (transferType == TT_FCNRETURN))
2451 ttyp = ctype_getReturnType (ttyp);
2455 ** check for null (don't need to check aliases??)
2458 if (sRef_possiblyNull (fref)
2459 && !usymtab_isGuarded (fref)
2460 && ctype_isRealAP (ttyp))
2462 if (!alkind_isLocal (tkind) && !alkind_isFresh (tkind)
2463 && !sRef_perhapsNull (tref)
2464 && !(transferType == TT_DOASSIGN))
2466 if (transferType == TT_GLOBINIT)
2468 if (sRef_isNotNull (tref))
2471 (FLG_SYNTAX, /*@i432 kuldge flag... */
2472 message ("%s %q initialized to %s value: %q",
2473 sRef_getScopeName (tref),
2474 sRef_unparse (tref),
2475 sRef_nullMessage (fref),
2476 generateText (fexp, texp, tref, transferType)),
2479 sRef_showNullInfo (fref);
2480 sRef_setNullError (tref);
2487 message ("%s %q initialized to %s value: %q",
2488 sRef_getScopeName (tref),
2489 sRef_unparse (tref),
2490 sRef_nullMessage (fref),
2491 generateText (fexp, texp, tref, transferType)),
2494 sRef_showNullInfo (fref);
2495 sRef_setNullError (tref);
2502 ((transferType == TT_FCNPASS) ? FLG_NULLPASS : FLG_NULLRET,
2503 message ("%q storage %q%s: %q",
2504 cstring_capitalize (sRef_nullMessage (fref)),
2505 sRef_unparseOpt (fref),
2506 transferNullMessage (transferType),
2507 generateText (fexp, texp, tref, transferType)),
2510 sRef_showNullInfo (fref);
2511 sRef_setNullError (fref);
2524 checkTransferAssignAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2525 /*@exposed@*/ sRef tref, exprNode texp, bool tfix,
2526 fileloc loc, transferKind transferType)
2528 alkind tkind = sRef_getAliasKind (tref);
2531 ** Assignment to same --- no errors, or state changes.
2532 ** This can happen when returned params are used.
2535 if (sRef_sameName (fref, tref))
2537 sRef_copyState (tref, fref);
2541 if ((alkind_isOnly (tkind) || alkind_isFresh (tkind)
2542 || alkind_isNewRef (tkind) || alkind_isOwned (tkind))
2543 && !(sRef_isDead (tref)
2544 || sRef_isStateUndefined (tref)
2545 || sRef_isUnuseable (tref)
2546 || sRef_isPartial (tref)
2547 || sRef_definitelyNull (tref)
2548 || sRef_isStackAllocated (tref)
2549 || sRef_isAllocIndexRef (tref))
2550 && !(sRef_same (fref, tref)) /* okay to assign to self (returned params) */
2551 && !(usymtab_isDefinitelyNull (tref)))
2553 if (context_getFlag (FLG_MUSTFREE))
2555 if (canLoseReference (tref, loc))
2561 if (sRef_hasLastReference (tref))
2565 message ("Last reference %q to %s storage %q(type %s) not released "
2566 "before assignment: %q",
2567 sRef_unparse (tref),
2568 alkind_unparse (tkind),
2569 sRef_unparseOpt (sRef_getAliasInfoRef (tref)),
2570 ctype_unparse (sRef_getType (tref)),
2571 generateText (fexp, texp, tref, transferType)),
2574 sRef_showRefLost (tref);
2579 if (context_inGlobalScope ())
2581 /* no errors for static initializations */
2586 ** don't report this error for a[i], since it could
2587 ** be a new element.
2590 if (alkind_isNewRef (tkind))
2595 ("%q %q(type %s) not released before assignment: %q",
2597 (alkind_isKillRef (sRef_getOrigAliasKind (tref))
2598 ? "Kill reference parameter" : "New reference"),
2599 sRef_unparseOpt (tref),
2600 ctype_unparse (sRef_getType (tref)),
2601 generateText (fexp, texp, tref, transferType)),
2604 sRef_showAliasInfo (tref);
2605 sRef_setAliasKind (tref, AK_ERROR, loc);
2609 (!(sRef_isUnknownArrayFetch (tref)
2610 && !context_getFlag (FLG_STRICTDESTROY))
2611 && !sRef_isUnionField (tref)
2612 && !sRef_isRelDef (tref)
2616 ("%s storage %q(type %s) not released before assignment: %q",
2617 alkind_capName (tkind),
2618 sRef_unparseOpt (tref),
2619 ctype_unparse (sRef_getType (tref)),
2620 generateText (fexp, texp, tref, transferType)),
2623 sRef_showAliasInfo (tref);
2635 fixAssignLhs (tref);
2637 if (sRef_isRefCounted (tref)) /* tkind might not be correct now */
2639 if (sRef_isNewRef (fref))
2641 sRef_setAliasKind (tref, AK_NEWREF, loc);
2643 else if (sRef_isConst (fref))
2645 /* for now, constants are not ref counted */
2646 sRef_setAliasKind (tref, AK_ERROR, loc);
2653 if (!sRef_isNSLocalVar (tref)
2654 && sRef_isRefCounted (fref)
2655 && sRef_isStateDefined (fref))
2659 message ("New reference %qto reference counted storage: %q",
2660 sRef_unparseOpt (tref),
2661 generateText (fexp, texp, tref, transferType)),
2667 ** Not for structures and unions, since assignments copy.
2670 if (sRef_isStack (fref)
2671 && !ctype_isSU (ctype_realType (sRef_getType (fref))))
2673 sRef_setAliasKindComplete (tref, AK_STACK, loc);
2676 if (sRef_isNSLocalVar (tref)
2677 && !sRef_isOwned (tref) /*< should only apply to static >*/
2678 && ctype_isMutable (sRef_getType (tref)))
2680 if (sRef_isOnly (fref) && sRef_isNew (fref))
2684 sRef_setFresh (tref, loc);
2691 ** requires sRef_isOnly (fref)
2695 checkOnlyTransferAux (sRef fref, exprNode fexp, bool ffix,
2696 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2697 fileloc loc, transferKind transferType)
2699 alkind tkind = sRef_getAliasKind (tref);
2701 if (sRef_isExposed (tref) || sRef_isObserver (tref))
2703 if (transferType == TT_FCNRETURN && sRef_isNew (fref)
2704 && !alkind_isError (tkind))
2708 message ("Only storage %q%q (will not be released): %q",
2709 sRef_unparseOpt (fref),
2710 transferErrorMessage (transferType, tkind),
2711 generateText (fexp, texp, tref, transferType)),
2714 sRef_showAliasInfo (fref);
2718 /* no errors for exposed transfers (is this good enough?) */
2720 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind) || alkind_isOwned (tkind))
2724 else if ((transferType == TT_FCNPASS)
2725 && (alkind_isUnknown (tkind)
2726 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2728 if (sRef_isFresh (fref)
2729 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2731 if (!ffix) sRef_setAliasKind (fref, AK_UNKNOWN, loc);
2734 else if (alkind_isLocal (tkind)
2735 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2737 if ((transferType == TT_DOASSIGN)
2738 && sRef_isNew (fref)
2739 && sRef_isOnly (fref))
2743 if (alkind_isUnknown (tkind)
2744 && sRef_isFileOrGlobalScope (sRef_getRootBase (tref)))
2747 (FLG_ONLYUNQGLOBALTRANS,
2748 message ("Only storage %q%q: %q",
2749 sRef_unparseOpt (fref),
2750 transferErrorMessage (transferType, tkind),
2751 generateText (fexp, texp, tref, transferType)),
2754 sRef_showAliasInfo (fref);
2755 sRef_setAliasKind (tref, AK_ERROR, loc);
2760 if (!error && !ffix)
2762 sRef_setFresh (tref, loc);
2767 if (alkind_isLocal (tkind))
2769 if (sRef_sameName (tref, fref))
2771 ; /* don't set this --- corresponds to return transfer */
2776 ** Don't set local to dependent. Error will
2777 ** be detected through aliasing. Except for
2781 if (!tfix && sRef_isThroughArrayFetch (fref)
2782 && context_getFlag (FLG_DEPARRAYS))
2784 sRef_setDependent (tref, loc);
2792 message ("Only storage %q%q: %q",
2793 sRef_unparseOpt (fref),
2794 transferErrorMessage (transferType, tkind),
2795 generateText (fexp, texp, tref, transferType)),
2798 sRef_showAliasInfo (fref);
2805 if (alkind_isError (tkind)
2806 || (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT)))
2808 flagcode_recordSuppressed (FLG_ONLYTRANS);
2812 if ((alkind_isKept (tkind) || alkind_isStack (tkind)
2813 || alkind_isDependent (tkind))
2814 && sRef_isNSLocalVar (tref))
2822 message ("Only storage %q%q: %q",
2823 sRef_unparseOpt (fref),
2824 transferErrorMessage (transferType, tkind),
2825 generateText (fexp, texp, tref, transferType)),
2828 sRef_showAliasInfo (fref);
2830 if (transferType == TT_DOASSIGN)
2833 ** alias kind unknown to suppress future messages
2836 if (!ffix && sRef_isNSLocalVar (sRef_getRootBase (fref)))
2838 sRef_clearAliasKind (fref);
2848 ** ??? same as checkOnly ?
2852 checkOwnedTransferAux (sRef fref, exprNode fexp, bool ffix,
2853 sRef tref, exprNode texp, bool tfix,
2854 fileloc loc, transferKind transferType)
2856 alkind tkind = sRef_getAliasKind (tref);
2858 if (sRef_isExposed (tref) || sRef_isObserver (tref))
2860 if (transferType == TT_FCNRETURN && sRef_isNew (fref))
2864 message ("Owned storage %q%q (will not be released): %q",
2865 sRef_unparseOpt (fref),
2866 transferErrorMessage (transferType, tkind),
2867 generateText (fexp, texp, tref, transferType)),
2870 sRef_showAliasInfo (fref);
2874 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind)
2875 || alkind_isDependent (tkind)
2876 || alkind_isOwned (tkind))
2880 else if (alkind_isLocal (tkind)
2881 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2883 if ((transferType == TT_DOASSIGN)
2884 && sRef_isNew (fref) && sRef_isOnly (fref))
2888 sRef_setFresh (tref, loc);
2895 else if ((transferType == TT_FCNPASS)
2896 && (alkind_isUnknown (tkind)
2897 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2899 if (sRef_isFresh (fref)
2900 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2902 if (!ffix) { sRef_clearAliasKind (fref); }
2907 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2909 flagcode_recordSuppressed (FLG_OWNEDTRANS);
2913 if (alkind_isKept (tkind) && sRef_isNSLocalVar (tref))
2921 message ("Owned storage %q%q: %q",
2922 sRef_unparseOpt (fref),
2923 transferErrorMessage (transferType, tkind),
2924 generateText (fexp, texp, tref, transferType)),
2929 if (transferType == TT_DOASSIGN)
2932 ** alias kind unknown to suppress future messages
2935 if (!ffix) { sRef_clearAliasKind (fref); }
2941 checkFreshTransferAux (sRef fref, exprNode fexp, bool ffix,
2942 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2943 fileloc loc, transferKind transferType)
2945 alkind tkind = sRef_getAliasKind (tref);
2948 ** error to return fresh as non-only
2951 if (transferType == TT_FCNRETURN
2952 && !(alkind_isOnly (tkind) || alkind_isNewRef (tkind)))
2954 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2956 flagcode_recordSuppressed (FLG_NEWREFTRANS);
2960 if (alkind_isError (tkind))
2964 sRef_killComplete (fref, loc);
2967 else if (alkind_isRefCounted (tkind))
2972 ("New reference returned without newref qualifier: %q",
2973 generateText (fexp, texp, tref, transferType)),
2976 sRef_showAliasInfo (fref);
2977 sRef_killComplete (fref, loc);
2984 message ("Fresh storage %q (should be only): %q",
2985 transferErrorMessage (transferType, tkind),
2986 generateText (fexp, texp, tref, transferType)),
2989 sRef_showAliasInfo (fref);
2990 sRef_killComplete (fref, loc);
2997 ** Okay to assign fresh to only, shared or unqualified.
2999 ** should generate other errors?
3002 if (alkind_isOnly (tkind))
3004 if (transferType == TT_DOASSIGN && !sRef_isFileOrGlobalScope (tref))
3008 if (!sRef_isNSLocalVar (tref))
3010 sRef_setKeptComplete (fref, loc);
3016 if (sRef_isConst (fref))
3024 sRef_killComplete (fref, loc);
3029 else if (alkind_isOwned (tkind))
3033 sRef_setDependentComplete (fref, loc);
3036 else if (alkind_isRefCounted (tkind)
3037 && (transferType == TT_FCNRETURN) && sRef_isFresh (fref))
3041 sRef_killComplete (fref, loc);
3044 else if (alkind_isKeep (tkind))
3048 if (!sRef_isNSLocalVar (tref))
3050 sRef_setKeptComplete (fref, loc);
3054 else if (alkind_isShared (tkind))
3056 if (!ffix) { sRef_setShared (fref, loc); }
3058 else if (alkind_isLocal (tkind) || alkind_isUnknown (tkind))
3060 if (transferType == TT_DOASSIGN || transferType == TT_FCNRETURN)
3063 ** local shares fresh. Make it owned/dependent.
3068 sRef_setOwned (tref, loc);
3073 sRef_setDependentComplete (fref, loc);
3076 /* NO! sRef_clearAliasKind (fref); */
3080 if (context_getFlag (FLG_PASSUNKNOWN))
3082 sRef_clearAliasKind (fref);
3093 checkTransferExposure (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
3094 sRef tref, exprNode texp, bool tfix,
3096 transferKind transferType)
3098 alkind fkind = sRef_getAliasKind (fref);
3099 alkind tkind = sRef_getAliasKind (tref);
3100 exkind tekind = sRef_getExKind (tref);
3102 if (sRef_isObserver (fref) && ctype_isMutable (sRef_getType (fref)))
3105 ** observer -> exposed or observer
3109 ** observer -> temp is okay [NO! really? only in function calls]
3112 if (sRef_isExposed (tref) || sRef_isObserver (tref)
3113 || alkind_isLocal (tkind))
3117 if ((transferType == TT_DOASSIGN) && alkind_isLocal (tkind))
3121 sRef_setAliasKindComplete (tref, fkind, loc);
3127 if (transferType == TT_FCNRETURN
3128 || transferType == TT_DOASSIGN
3129 || transferType == TT_FIELDASSIGN
3130 || transferType == TT_GLOBINIT)
3132 bool hasError = FALSE;
3134 if (exprNode_isStringLiteral (fexp)
3135 && transferType == TT_GLOBINIT)
3137 hasError = optgenerror
3139 message ("Read-only string literal storage %q%q: %q",
3140 sRef_unparseOpt (fref),
3141 transferErrorExpMessage (transferType, tekind),
3142 generateText (fexp, texp, tref, transferType)),
3145 sRef_setAliasKind (fref, AK_ERROR, fileloc_undefined);
3149 if ((transferType == TT_DOASSIGN
3150 || transferType == TT_FIELDASSIGN)
3151 && (sRef_isNSLocalVar (tref)
3152 || (exprNode_isStringLiteral (fexp)
3153 && ctype_isRealArray (exprNode_getType (texp)))))
3155 ; /* No error for local assignment or assignment
3156 to static array (copies string). */
3160 if (exprNode_isStringLiteral (fexp))
3162 hasError = optgenerror
3165 ("Read-only string literal storage %q%q: %q",
3166 sRef_unparseOpt (fref),
3167 transferErrorExpMessage (transferType, tekind),
3168 generateText (fexp, texp, tref, transferType)),
3175 hasError = optgenerror
3178 ("Observer storage %q%q: %q",
3179 sRef_unparseOpt (fref),
3180 transferErrorExpMessage (transferType, tekind),
3181 generateText (fexp, texp, tref, transferType)),
3189 if (transferType != TT_GLOBINIT)
3191 sRef_showExpInfo (fref);
3192 sRef_setAliasKind (tref, AK_ERROR, loc);
3197 if (transferType == TT_DOASSIGN && !tfix)
3199 DPRINTF (("Setting unknown!"));
3200 /* sRef_setAliasKind (tref, AK_ERROR, loc); */
3204 else /* TT_FCNPASS */
3206 llassert (transferType == TT_FCNPASS);
3208 if (alkind_isTemp (tkind)
3209 || alkind_isDependent (tkind)
3210 || alkind_isRefCounted (tkind))
3216 if (!alkind_isError (tkind))
3220 message ("Observer storage %q%q: %q",
3221 sRef_unparseOpt (fref),
3222 transferErrorMessage (transferType, tkind),
3223 generateText (fexp, texp, tref, transferType)),
3226 sRef_showExpInfo (fref);
3227 sRef_clearAliasState (fref, loc);
3234 else if (sRef_isExposed (fref) && ctype_isMutable (sRef_getType (fref)))
3236 if (transferType == TT_FCNRETURN)
3238 if (!(sRef_isExposed (tref) || sRef_isObserver (tref)
3239 || sRef_isParam (fref)))
3243 message ("Exposed storage %q%q: %q",
3244 sRef_unparseOpt (fref),
3245 transferErrorExpMessage (transferType, tekind),
3246 generateText (fexp, texp, tref, transferType)),
3249 sRef_showExpInfo (fref);
3253 else if (transferType == TT_FCNPASS)
3255 if (!(sRef_isExposed (tref)
3256 || sRef_isObserver (tref)
3257 || (alkind_isUnknown (tkind)
3258 || alkind_isDependent (tkind)
3259 || alkind_isTemp (tkind)
3260 || alkind_isKillRef (tkind)
3261 || alkind_isRefCounted (tkind))))
3263 if (alkind_isUnique (tkind) || alkind_isError (tkind))
3270 message ("Exposed storage %q%q: %q",
3271 sRef_unparseOpt (fref),
3272 transferErrorMessage (transferType, tkind),
3273 generateText (fexp, texp, tref, transferType)),
3276 sRef_showExpInfo (fref);
3277 sRef_clearAliasState (fref, loc);
3287 else if (transferType == TT_DOASSIGN)
3289 if (!(sRef_isExposed (tref)
3290 || !sRef_isCvar (tref)
3291 || (alkind_isUnknown (tkind)
3292 || alkind_isDependent (tkind)
3293 || alkind_isRefCounted (tkind)
3294 || alkind_isNewRef (tkind)
3295 || alkind_isFresh (tkind)
3296 || alkind_isLocal (tkind))))
3300 message ("Exposed storage %q%q: %q",
3301 sRef_unparseOpt (fref),
3302 transferErrorExpMessage (transferType, tekind),
3303 generateText (fexp, texp, tref, transferType)),
3306 sRef_showExpInfo (fref);
3309 if (!tfix) { sRef_setExposed (tref, loc); }
3313 llassert (transferType == TT_GLOBPASS
3314 || transferType == TT_GLOBRETURN
3315 || transferType == TT_PARAMRETURN
3316 || transferType == TT_LEAVETRANS
3317 || transferType == TT_GLOBINIT);
3327 ** returns TRUE if there is no error reported
3329 ** if fixt, don't change tref (except if error reported.)
3330 ** if fixf, don't change fref (except if error reported.)
3334 checkTransferAux (exprNode fexp, /*@exposed@*/ sRef fref, bool ffix,
3335 exprNode texp, /*@exposed@*/ sRef tref, bool tfix,
3336 fileloc loc, transferKind transferType)
3340 bool isassign = (transferType == TT_DOASSIGN);
3341 bool isfieldassign = (transferType == TT_FIELDASSIGN);
3342 bool iseitherassign = isassign || (transferType == TT_FIELDASSIGN);
3343 bool isfcnpass = (transferType == TT_FCNPASS);
3344 bool isfcnreturn = (transferType == TT_FCNRETURN);
3351 checkTransferNullAux (fref, fexp, ffix, tref, texp, tfix,
3358 checkTransferAssignAux (fref, fexp, ffix, tref, texp, tfix,
3363 ** Check for definition
3367 ** errors passing out params already detected in checkAnyCall
3375 || (!sRef_isNSLocalVar (tref)
3376 && (sRef_isAnyDefined (tref) || !sRef_stateKnown (tref))))
3380 if (!ynm_toBoolRelaxed
3381 (checkCompletelyDefined (fexp, fref, fref,
3384 loc, transferType, 0, TRUE)))
3392 if (defok && iseitherassign)
3394 sRef_setDefState (tref, sRef_getDefState (fref), loc);
3403 checkTransferExposure (fref, fexp, ffix, tref, texp, tfix,
3406 fkind = sRef_getAliasKind (fref);
3407 tkind = sRef_getAliasKind (tref);
3413 if (alkind_isOnly (fkind))
3416 checkOnlyTransferAux (fref, fexp, ffix,
3420 else if (alkind_isFresh (fkind))
3423 checkFreshTransferAux (fref, fexp, ffix,
3427 else if (alkind_isOwned (fkind))
3430 checkOwnedTransferAux (fref, fexp, ffix,
3434 else if (alkind_isDependent (fkind))
3438 (sRef_isExposed (tref) || sRef_isObserver (tref)))
3442 else if ((alkind_isOnly (tkind) || alkind_isKeep (tkind)
3443 || alkind_isOwned (tkind))
3444 || (!isfcnpass && alkind_isTemp (tkind)))
3448 if (sRef_isLocalVar (fref))
3450 sRef depRef = dependentReference (fref);
3452 if (sRef_isValid (depRef) && sRef_isLocalVar (depRef))
3455 sRef_kill (depRef, loc);
3456 sRef_kill (fref, loc);
3466 if (canLoseLocalReference (fref, loc))
3474 (FLG_DEPENDENTTRANS,
3475 message ("%s storage %q%q: %q",
3476 alkind_capName (fkind),
3477 sRef_unparseOpt (fref),
3478 transferErrorMessage (transferType, tkind),
3479 generateText (fexp, texp, tref, transferType)),
3482 DPRINTF (("Here: %s / %s",
3483 sRef_unparseFull (fref),
3484 sRef_unparseFull (tref)));
3486 sRef_showAliasInfo (fref);
3492 if (isassign && (alkind_isFresh (tkind) || alkind_isLocal (tkind)))
3496 sRef_setDependent (tref, loc);
3501 else if (alkind_isShared (fkind))
3508 if (alkind_isOnly (tkind)
3510 && (!(sRef_isObserver (tref) || sRef_isExposed (tref))
3511 && alkind_isTemp (tkind))))
3515 message ("%s storage %q%q: %q",
3516 alkind_capName (fkind),
3517 sRef_unparseOpt (fref),
3518 transferErrorMessage (transferType, tkind),
3519 generateText (fexp, texp, tref, transferType)),
3522 sRef_showAliasInfo (fref);
3527 if (alkind_isFresh (tkind) || alkind_isLocal (tkind))
3529 sRef_setShared (tref, loc);
3533 else if (alkind_isKeep (fkind))
3537 if (alkind_isKeep (tkind)
3538 || alkind_isLocal (tkind)
3539 || (isfcnreturn && sRef_isExposed (tref))
3541 && (alkind_isOnly (tkind) || alkind_isOwned (tkind))))
3543 sRef_setKept (fref, loc);
3546 && (alkind_isTemp (tkind) || alkind_isOwned (tkind)))
3552 if (!alkind_isError (tkind))
3556 message ("%s storage %q: %q",
3557 alkind_capName (fkind),
3558 transferErrorMessage (transferType, tkind),
3559 generateText (fexp, texp, tref, transferType)),
3562 sRef_showAliasInfo (fref);
3567 else if (alkind_isTemp (fkind) || alkind_isKept (fkind))
3573 if (alkind_isOnly (tkind)
3574 || alkind_isShared (tkind)
3575 || (alkind_isTemp (fkind)
3576 && !isfcnreturn && alkind_isDependent (tkind))
3577 || alkind_isOwned (tkind)
3578 || alkind_isKeep (tkind))
3580 if (!exprNode_isNullValue (fexp)
3581 && (ctype_isMutable (exprNode_getType (fexp))
3582 || (ctype_isArray (exprNode_getType (fexp))
3583 && sRef_isParam (fref)))
3584 && (!iseitherassign || sRef_isReference (tref)))
3586 if (sRef_isThroughArrayFetch (fref))
3589 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3590 FLG_STRICTUSERELEASED,
3591 message ("%s storage %q%q: %q",
3592 alkind_capName (fkind),
3593 sRef_unparseOpt (fref),
3594 transferErrorMessage (transferType, tkind),
3595 generateText (fexp, texp, tref, transferType)),
3598 sRef_showAliasInfo (fref);
3604 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3605 message ("%s storage %q%q: %q",
3606 alkind_capName (fkind),
3607 sRef_unparseOpt (fref),
3608 transferErrorMessage (transferType, tkind),
3609 generateText (fexp, texp, tref, transferType)),
3612 sRef_showAliasInfo (fref);
3618 else if (alkind_isRefCounted (fkind) || alkind_isKillRef (fkind))
3620 if (alkind_isNewRef (tkind))
3623 ** check that the refs field has been modified
3626 if (!sRef_isConst (fref))
3630 message ("Reference counted storage returned without modifying "
3631 "reference count: %s",
3632 exprNode_unparse (fexp)),
3636 else if (iseitherassign)
3638 if (alkind_isRefCounted (fkind))
3640 if (!sRef_isLocalVar (tref))
3645 ("Assignment to non-local from reference counted storage: %s",
3646 exprNode_unparse (fexp)),
3648 ("Reference counted storage should call a function returning "
3649 "a newref instead of direct assignments."),
3660 if (alkind_isRefCounted (tkind) || alkind_isTemp (tkind))
3662 /* okay --- no change in state */
3664 else if (alkind_isKillRef (tkind))
3666 if (!ffix && !tfix && !(transferType == TT_FCNRETURN))
3668 sRef_killComplete (fref, loc);
3673 if (!alkind_isError (tkind))
3677 message ("Reference counted storage %q: %q",
3678 transferErrorMessage (transferType, tkind),
3679 generateText (fexp, texp, tref, transferType)),
3692 if (alkind_isOnly (tkind) || alkind_isKeep (tkind))
3694 if (sRef_isAddress (fref))
3697 (FLG_IMMEDIATETRANS,
3698 message ("Immediate address %q %q: %q",
3699 sRef_unparse (fref),
3700 transferErrorMessage (transferType, tkind),
3701 generateText (fexp, texp, tref, transferType)),
3704 sRef_setAliasKind (fref, AK_ERROR, loc);
3708 if ((alkind_isUnknown (fkind) || alkind_isStatic (fkind))
3709 && !sRef_isDefinitelyNull (fref)
3711 && (!exprNode_isNullValue (fexp)))
3713 flagcode errkind = alkind_isStatic (fkind)
3714 ? FLG_STATICTRANS : FLG_UNKNOWNTRANS;
3716 if (transferType == TT_GLOBINIT)
3718 if (errkind == FLG_STATICTRANS)
3720 errkind = FLG_STATICINITTRANS;
3724 errkind = FLG_UNKNOWNINITTRANS;
3730 message ("%s storage %s %q: %q",
3731 alkind_capName (fkind),
3732 exprNode_unparse (fexp),
3733 transferErrorMessage (transferType, tkind),
3734 generateText (fexp, texp, tref, transferType)),
3737 sRef_showAliasInfo (fref);
3742 /* don't kill shared to suppress future messages */
3743 if (!alkind_isShared (fkind))
3749 /*< yuk! should do this in aliasaux >*/
3751 if (!sRef_isNSLocalVar (tref) && !sRef_sameName (fref, tref))
3755 sRef_setKeptComplete (fref, loc);
3759 sRef_setKept (fref, loc);
3770 if (alkind_isKeep (tkind))
3772 sRef_setKeptComplete (fref, loc);
3776 sRef_killComplete (fref, loc);
3781 if (alkind_isKeep (tkind))
3783 sRef_setKept (fref, loc);
3787 sRef_kill (fref, loc);
3794 else if (alkind_isOwned (tkind))
3796 /* don't kill shared to suppress future messages */
3797 if (!alkind_isShared (fkind))
3800 || !sRef_sameName (fref, tref)) /* result of return parameter */
3806 sRef_setDependentComplete (fref, loc);
3810 sRef_setDependent (fref, loc);
3816 else if (alkind_isShared (tkind))
3818 if (alkind_isFresh (fkind) || alkind_isLocal (fkind))
3822 sRef_setShared (fref, loc);
3826 else if (alkind_isUnknown (tkind) && context_getFlag (FLG_MEMIMPLICIT))
3828 if (alkind_isDependent (fkind))
3830 if (!exprNode_isNullValue (fexp)
3831 && ctype_isMutable (exprNode_getType (fexp))
3832 && (!iseitherassign || sRef_isReference (tref)))
3834 if (canLoseReference (fref, loc))
3841 (FLG_DEPENDENTTRANS,
3842 message ("%s storage %q%q: %q",
3843 alkind_capName (fkind),
3844 sRef_unparseOpt (fref),
3845 transferErrorMessage (transferType, tkind),
3846 generateText (fexp, texp, tref, transferType)),
3849 DPRINTF (("Here: %s / %s", sRef_unparseFull (fref),
3850 sRef_unparseFull (tref)));
3851 sRef_showAliasInfo (fref);
3857 else if (alkind_isNewRef (tkind))
3861 sRef_killComplete (fref, loc);
3864 else if (alkind_isKillRef (tkind))
3866 if (transferType == TT_FCNRETURN)
3868 if (sRef_isNewRef (fref))
3872 message ("New reference returned as temp reference: %q",
3873 generateText (fexp, texp, tref, transferType)),
3876 sRef_showAliasInfo (fref);
3882 if (sRef_isNewRef (fref))
3884 sRef_killComplete (fref, loc);
3888 if (sRef_isRefCounted (fref)
3889 && sRef_isCvar (fref)
3890 && !sRef_isLocalVar (fref))
3895 ("External reference counted storage released: %q",
3896 generateText (fexp, texp, tref, transferType)),
3899 sRef_showAliasInfo (fref);
3915 checkMetaStateConsistent (/*@exposed@*/ sRef fref, sRef tref,
3916 fileloc loc, /*@unused@*/ transferKind transferType)
3919 ** Checks if it is consistent to leave storage marked as tref in state of fref.
3922 valueTable fvalues = sRef_getValueTable (fref);
3923 valueTable tvalues = sRef_getValueTable (tref);
3925 DPRINTF (("Metastate consistent: %s => %s",
3926 sRef_unparseFull (fref),
3927 sRef_unparseFull (tref)));
3929 if (valueTable_isUndefined (tvalues) || valueTable_isUndefined (fvalues)) {
3930 /* Cannot check without value tables. An error was already detected. */
3931 DPRINTF (("No value table: %s / %s",
3932 bool_unparse (valueTable_isUndefined (tvalues)),
3933 bool_unparse (valueTable_isUndefined (fvalues))));
3937 valueTable_elements (fvalues, fkey, fval) {
3939 metaStateInfo minfo;
3941 DPRINTF (("Transfer: %s", fkey));
3942 tval = valueTable_lookup (tvalues, fkey);
3943 minfo = context_lookupMetaStateInfo (fkey);
3945 if (!stateValue_isDefined (tval))
3947 if (ctype_isUnknown (sRef_getType (fref)))
3949 ; /* Okay, put in default values without knowing type */
3954 DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
3955 sRef_unparseFull (tref),
3961 llassert (metaStateInfo_isDefined (minfo));
3963 if (stateValue_isError (fval) || stateValue_isError (tval))
3967 else if (!stateValue_sameValue (fval, tval))
3969 DPRINTF (("Check: %s / %s / %s / %s", fkey,
3970 metaStateInfo_unparse (minfo),
3971 stateValue_unparse (fval),
3972 stateValue_unparse (tval)));
3974 if (sRef_isDefinitelyNull (fref)
3975 || usymtab_isDefinitelyNull (fref))
3977 ; /* No errors for null values in state transfers. */
3984 ("Invalid transfer from %q %x to %q",
3985 stateValue_unparseValue (fval, minfo),
3986 sRef_unparse (fref),
3987 stateValue_unparseValue (tval, minfo)),
3990 sRef_showMetaStateInfo (fref, fkey);
4000 DPRINTF (("Transfer: %s %s -> %s",
4001 fkey, stateValue_unparse (fval), stateValue_unparse (tval)));
4002 } end_valueTable_elements ;
4006 checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref,
4007 fileloc loc, transferKind /*@i32@*/ transferType)
4009 valueTable fvalues = sRef_getValueTable (fref);
4010 valueTable tvalues = sRef_getValueTable (tref);
4012 DPRINTF (("Metastate transfer: from %s", exprNode_unparse (fexp)));
4014 DPRINTF (("Metastate transfer: %s => %s",
4015 sRef_unparseFull (fref),
4016 sRef_unparseFull (tref)));
4018 if (valueTable_isUndefined (tvalues) || valueTable_isUndefined (fvalues)) {
4019 /* Cannot check without value tables. An error was already detected. */
4020 DPRINTF (("No value table: %s / %s",
4021 bool_unparse (valueTable_isUndefined (tvalues)),
4022 bool_unparse (valueTable_isUndefined (fvalues))));
4026 valueTable_elements (fvalues, fkey, fval) {
4028 metaStateInfo minfo;
4029 stateCombinationTable sctable;
4033 DPRINTF (("Transfer: %s", fkey));
4034 tval = valueTable_lookup (tvalues, fkey);
4035 minfo = context_lookupMetaStateInfo (fkey);
4037 if (!stateValue_isDefined (tval))
4039 if (ctype_isUnknown (sRef_getType (fref)))
4041 ; /* Okay, put in default values without knowing type */
4046 DPRINTF (("Metastate transfer: %s => %s",
4047 exprNode_unparse (fexp), exprNode_unparse (texp)));
4048 DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
4049 sRef_unparseFull (tref),
4055 llassert (metaStateInfo_isDefined (minfo));
4057 if (stateValue_isError (fval))
4061 else if (stateValue_isError (tval))
4063 if (sRef_isLocalVar (tref) && transferType == TT_DOASSIGN)
4065 /* Local assignments just replace state. */
4066 stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
4067 DPRINTF (("Update: %s", stateValue_unparse (tval)));
4069 else if (transferType == TT_FCNRETURN)
4071 ; /* Returning from an unannotated function */
4075 DPRINTF (("Transfer to error: %s / %s", sRef_unparseFull (tref),
4076 transferType_unparse (transferType)));
4081 DPRINTF (("Check: %s / %s / %s / %s", fkey,
4082 metaStateInfo_unparse (minfo),
4083 stateValue_unparse (fval),
4084 stateValue_unparse (tval)));
4086 sctable = metaStateInfo_getTransferTable (minfo);
4087 msg = cstring_undefined;
4089 nval = stateCombinationTable_lookup (sctable,
4090 stateValue_getValue (fval),
4091 stateValue_getValue (tval),
4094 if (transferType == TT_DOASSIGN && sRef_isLocalVar (tref))
4096 /* Local assignments just replace state. */
4097 DPRINTF (("No transfer error assigning to local: %s", msg));
4098 stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
4099 DPRINTF (("Update: %s", stateValue_unparse (tval)));
4103 if (cstring_isDefined (msg))
4105 /*@i32 print extra info for assignments@*/
4110 ("Invalid transfer from %q %x to %q (%s): %q",
4111 stateValue_unparseValue (fval, minfo),
4112 sRef_unparse (fref),
4113 stateValue_unparseValue (tval, minfo),
4115 transferErrorExcerpt (transferType, fexp, texp)),
4118 sRef_showMetaStateInfo (fref, fkey);
4122 DPRINTF (("Suppressed transfer error: %s", msg));
4127 if (transferType == TT_FCNRETURN)
4130 ** Returning this reference from a function, mark this reference
4131 ** so no lost reference errors are returned.
4134 stateValue_updateValueLoc (fval, stateValue_error, loc);
4136 else if (stateValue_getValue (fval) != nval)
4138 stateValue_updateValueLoc (fval, nval, loc);
4149 DPRINTF (("Transfer: %s %s -> %s",
4150 fkey, stateValue_unparse (fval), stateValue_unparse (tval)));
4151 } end_valueTable_elements ;
4155 ** assigns fexp := tref or passes fexp as a parameter, or returns fexp.
4157 ** For assignments, sets alias and definition state accordingly.
4161 checkTransfer (exprNode fexp, /*@dependent@*/ sRef fref,
4162 exprNode texp, /*@dependent@*/ sRef tref,
4163 fileloc loc, transferKind transferType)
4167 if (context_inProtectVars ())
4172 DPRINTF (("Check transfer: %s => %s",
4173 sRef_unparse (fref),
4174 sRef_unparse (tref)));
4175 DPRINTF (("Check transfer: %s => %s",
4176 exprNode_unparse (fexp),
4177 exprNode_unparse (texp)));
4179 checkMetaStateTransfer (fexp, fref, texp, tref, loc, transferType);
4182 ** for local references, we need to check
4183 ** the transfer for all possible aliases.
4186 if (sRef_isLocalVar (tref) && transferType != TT_DOASSIGN)
4188 sRefSet alias = usymtab_allAliases (tref);
4190 sRefSet_realElements (alias, atref)
4192 sRef abase = sRef_getRootBase (atref);
4194 if (sRef_isKnown (atref)
4195 && !sRef_isLocalVar (abase)
4196 && !sRef_isExternal (abase))
4198 atref = sRef_updateSref (atref);
4200 if (sRef_hasName (atref))
4202 if (!sRef_isNew (atref)
4203 && !sRef_sameName (tref, atref))
4205 context_setAliasAnnote (atref, tref);
4208 checkTransferAux (fexp, fref, TRUE,
4212 context_clearAliasAnnote ();
4215 } end_sRefSet_realElements;
4217 sRefSet_free (alias);
4220 if (sRef_isLocalVar (fref))
4222 sRefSet alias = usymtab_allAliases (fref);
4224 sRefSet_realElements (alias, afref)
4226 sRef abase = sRef_getRootBase (afref);
4228 if (sRef_isKnown (afref)
4229 && !sRef_isLocalVar (abase)
4230 && !sRef_isExternal (abase))
4232 afref = sRef_updateSref (afref);
4234 if (sRef_hasName (afref))
4236 if (!sRef_isNew (afref)
4237 && !sRef_sameName (afref, fref))
4239 context_setAliasAnnote (afref, fref);
4242 checkTransferAux (fexp, afref, FALSE,
4246 context_clearAliasAnnote ();
4249 } end_sRefSet_realElements;
4251 sRefSet_free (alias);
4255 checkTransferAux (fexp, fref, FALSE, texp, tref, FALSE,
4260 static /*@exposed@*/ sRef
4261 dependentReference (sRef sr)
4263 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4265 DPRINTF (("Dependent reference: %s", sRef_unparse (sr)));
4266 DPRINTF (("Aliases: %s", sRefSet_unparse (ab)));
4269 ** If there is a local variable that aliases sr, then there is no
4270 ** error. Make the local an only.
4273 if (!sRefSet_isEmpty (ab))
4275 sRef res = sRef_undefined;
4277 DPRINTF (("Here we are!"));
4280 ** make one an only, others alias it
4283 sRefSet_realElements (ab, current)
4285 if (sRef_isOwned (current))
4290 } end_sRefSet_realElements;
4292 if (sRef_isInvalid (res))
4295 ** evans - 2001-03-24
4296 ** No owned element, just choose one!
4297 ** (Any reason for preference?)
4300 res = sRefSet_choose (ab);
4307 return sRef_undefined;
4310 bool canLoseReference (/*@dependent@*/ sRef sr, fileloc loc)
4312 bool gotone = FALSE;
4313 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4316 ** if there is a local variable that aliases sr, then there is no
4317 ** error. Make the local an only.
4320 if (!sRefSet_isEmpty (ab))
4323 ** make one an only, others alias it
4326 sRefSet_realElements (ab, current)
4328 sRef_setLastReference (current, sr, loc);
4331 } end_sRefSet_realElements;
4339 bool canLoseLocalReference (/*@dependent@*/ sRef sr, fileloc loc)
4341 bool gotone = FALSE;
4342 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4345 ** if there is a local variable that aliases sr, then there is no
4346 ** error. Make the local an only.
4349 if (!sRefSet_isEmpty (ab))
4352 ** make one an only, others alias it
4355 sRefSet_realElements (ab, current)
4357 if (sRef_isRealLocalVar (sRef_getRootBase (current)))
4359 sRef_setLastReference (current, sr, loc);
4363 } end_sRefSet_realElements;