2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 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 "aliasChecks.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 checkLeaveTrans (uentry p_actual, transferKind p_transferType);
35 static void checkTransfer (exprNode p_fexp, sRef p_fref,
36 exprNode p_texp, sRef p_tref,
37 fileloc p_loc, transferKind p_transferType);
38 static void checkGlobTrans (uentry p_glob, transferKind p_type);
41 checkCompletelyDefined (exprNode p_fexp, sRef p_fref,
42 exprNode p_texp, sRef p_tref,
43 bool p_topLevel, bool p_inUnion, bool p_directUnion,
44 fileloc p_loc, transferKind p_transferType, int p_depth,
47 static /*@exposed@*/ sRef dependentReference (sRef p_sr);
48 static bool canLoseLocalReference (sRef p_sr, fileloc p_loc) ;
50 /* added DRL 8/19/200- */
52 checkTransferNullTerminatedAux (sRef p_fref, exprNode p_fexp,
53 /*@unused@*/ bool p_ffix,
54 sRef p_tref, exprNode p_texp, /*@unused@*/ bool p_tfix,
55 fileloc p_loc, transferKind p_transferType);
57 ** returns the most specific alkind
60 alkind alkind_resolve (alkind a1, alkind a2)
62 if (a1 == AK_UNKNOWN || a1 == AK_ERROR) return a2;
63 if (a2 == AK_UNKNOWN || a2 == AK_ERROR || a2 == AK_LOCAL) return a1;
64 if (a1 == AK_LOCAL) return a2;
72 ** FCNRETURN return fref; tref is return type
73 ** GLOBASSIGN tref = fref;
74 ** FCNPASS call (fref) ; tref is the argument type
78 static /*@only@*/ cstring
79 transferErrorMessage (transferKind transferType, alkind tkind) /*@*/
84 return (message ("returned as %s", alkind_unparse (tkind)));
86 return (message ("assigned to %s", alkind_unparse (tkind)));
88 return (message ("assigned to %s", alkind_unparse (tkind)));
90 return (message ("used as initial value for %s",
91 alkind_unparse (tkind)));
93 return (message ("passed as %s param", alkind_unparse (tkind)));
100 transferErrorExpMessage (transferKind transferType, exkind tkind) /*@*/
102 if (exkind_isUnknown (tkind))
104 switch (transferType)
107 return (cstring_makeLiteral ("returned without qualification"));
110 return (cstring_makeLiteral ("assigned to unqualified reference"));
112 return (cstring_makeLiteral ("passed without qualification"));
114 return (cstring_makeLiteral ("used as initial value for unqualified storage"));
120 switch (transferType)
123 return (message ("returned as %s", exkind_unparse (tkind)));
126 return (message ("assigned to %s", exkind_unparse (tkind)));
128 return (message ("passed as %s param", exkind_unparse (tkind)));
136 static /*@observer@*/ cstring
137 transferNullMessage (transferKind transferType) /*@*/
139 switch (transferType)
142 return (cstring_makeLiteralTemp ("returned as non-null"));
145 return (cstring_makeLiteralTemp ("assigned to non-null"));
147 return (cstring_makeLiteralTemp ("initialized to non-null"));
149 return (cstring_makeLiteralTemp ("passed as non-null param"));
155 static /*@observer@*/ cstring
156 transferNTMessage (transferKind transferType) /*@*/
158 switch (transferType)
161 return (cstring_makeLiteralTemp ("returned as nullterminated"));
164 return (cstring_makeLiteralTemp ("assigned to nullterminated"));
166 return (cstring_makeLiteralTemp ("initialized to nullterminated"));
168 return (cstring_makeLiteralTemp ("passed as nullterminated param"));
174 static /*@dependent@*/ exprNode atFunction = exprNode_undefined;
175 static int atArgNo = 0;
176 static int atNumArgs = 0;
178 static cstring generateText (exprNode e1, exprNode e2,
179 sRef tref, transferKind tt)
182 if (tt == TT_DOASSIGN || tt == TT_GLOBINIT)
184 return (message ("%s = %s", exprNode_unparse (e2),
185 exprNode_unparse (e1)));
187 else if (tt == TT_FIELDASSIGN)
189 return (message ("%s = %s (field %q)",
190 exprNode_unparse (e2),
191 exprNode_unparse (e1),
192 sRef_unparse (tref)));
194 else if (tt == TT_FCNPASS)
196 return (message ("%s (%s%s%s)",
197 exprNode_unparse (atFunction),
198 (atArgNo == 1 ? cstring_undefined
199 : cstring_makeLiteralTemp ("..., ")),
200 exprNode_unparse (e1),
201 (atArgNo == atNumArgs ? cstring_undefined
202 : cstring_makeLiteralTemp (", ..."))));
206 return (cstring_copy (exprNode_unparse (e1)));
210 static /*@observer@*/ cstring
211 transferType_unparse (transferKind transferType) /*@*/
213 switch (transferType)
216 return (cstring_makeLiteralTemp ("Returned"));
219 return (cstring_makeLiteralTemp ("Assigned"));
221 return (cstring_makeLiteralTemp ("Passed"));
223 return (cstring_makeLiteralTemp ("Initialized"));
225 return (cstring_makeLiteralTemp ("GLOB RETURN!"));
227 return (cstring_makeLiteralTemp ("GLOB PASS!"));
229 return (cstring_makeLiteralTemp ("PARAM RETURN!"));
231 return (cstring_makeLiteralTemp ("LEAVE TRANS!"));
237 static /*@observer@*/ cstring udError (sRef s)
241 return cstring_makeLiteralTemp ("released");
243 else if (sRef_isAllocated (s))
245 return cstring_makeLiteralTemp ("allocated but not defined");
249 return cstring_makeLiteralTemp ("undefined");
254 cstring defExpl (sRef s) /*@*/
256 sRef rb = sRef_getRootBase (s);
258 if (sRef_sameName (rb, s))
260 if (sRef_isAllocated (s))
262 return cstring_makeLiteral (" (allocated only)");
264 return cstring_undefined;
268 return (message (" (%q is %s)", sRef_unparse (s), udError (s)));
273 ** returns TRUE if fref is completely defined.
274 ** if !report, returns TRUE unless error is at the deep level.
278 checkCompletelyDefined (exprNode fexp, sRef fref,
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 if (depth > MAXDEPTH)
292 ("Check definition limit exceeded, checking %q. "
293 "This either means there is a variable with at least "
294 "%d indirections apparent in the program text, or "
295 "there is a bug in LCLint.",
302 if (!sRef_isKnown (fref))
307 if (alkind_isStack (fkind))
309 ctype rt = ctype_realType (sRef_getType (tref));
311 if (ctype_isMutable (rt) && !ctype_isSU (rt))
313 if (transferType == TT_PARAMRETURN)
318 ("Stack-allocated storage %qreachable from parameter %q",
319 sRef_unparseOpt (fref),
320 sRef_unparse (sRef_getRootBase (fref))),
323 sRef_showAliasInfo (fref);
326 else if (transferType == TT_GLOBRETURN)
331 ("Stack-allocated storage %qreachable from global %q",
332 sRef_unparseOpt (fref),
333 sRef_unparse (sRef_getRootBase (fref))),
336 sRef_showAliasInfo (fref);
339 else if (transferType == TT_FCNRETURN)
344 ("Stack-allocated storage %qreachable from return value: %s",
345 sRef_unparseOpt (fref),
346 exprNode_unparse (fexp)),
349 sRef_showAliasInfo (fref);
361 if ((sRef_isObserver (fref) && !sRef_isObserver (tref))
362 || (sRef_isExposed (fref) && !(sRef_isObserver (tref)
363 || sRef_isExposed (tref))))
365 flagcode code = (sRef_isObserver (fref)
366 ? FLG_OBSERVERTRANS : FLG_EXPOSETRANS);
368 if (!sRef_isStateLive (fref))
370 ; /* no error (will be a definition error) */
372 else if (transferType == TT_DOASSIGN
373 || transferType == TT_FIELDASSIGN
374 || transferType == TT_GLOBINIT
375 || transferType == TT_FCNPASS)
379 else if (transferType == TT_PARAMRETURN)
384 ("%s storage %qreachable from %s parameter",
385 exkind_capName (sRef_getExKind (fref)),
386 sRef_unparseOpt (fref),
387 exkind_unparseError (sRef_getExKind (tref))),
390 sRef_showExpInfo (fref);
391 sRef_setExKind (fref, XO_UNKNOWN, loc);
394 else if (transferType == TT_LEAVETRANS)
398 else if (transferType == TT_GLOBINIT)
403 ("%s storage %qreachable from %s initial value",
404 exkind_capName (sRef_getExKind (fref)),
405 sRef_unparseOpt (fref),
406 exkind_unparseError (sRef_getExKind (tref))),
409 sRef_showExpInfo (fref);
410 sRef_setExKind (fref, XO_UNKNOWN, loc);
413 else if (transferType == TT_GLOBRETURN)
418 ("%s storage %qreachable from %s global",
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_FCNRETURN)
433 ("%s storage %qreachable from %s return value",
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);
445 llcontbug (message ("Transfer type: %s",
446 transferType_unparse (transferType)));
451 ("%s storage %qreachable from %s return value",
452 exkind_capName (sRef_getExKind (fref)),
453 sRef_unparseOpt (fref),
454 exkind_unparseError (sRef_getExKind (tref))),
457 sRef_showExpInfo (fref);
458 sRef_setExKind (fref, XO_UNKNOWN, loc);
464 if (!alkind_compatible (fkind, tkind))
466 if (fkind == AK_UNKNOWN && !sRef_isStateLive (fref))
468 ; /* no error (will be a definition error) */
470 else if (transferType == TT_DOASSIGN)
474 else if (transferType == TT_FCNPASS)
476 if (alkind_isKnown (sRef_getAliasKind (tref)))
481 ("Storage %qreachable from passed parameter "
482 "is %s (should be %s): %s",
483 sRef_unparseOpt (fref),
484 alkind_unparse (sRef_getAliasKind (fref)),
485 alkind_unparse (sRef_getAliasKind (tref)),
486 exprNode_unparse (fexp)),
489 sRef_showAliasInfo (fref);
493 else if (transferType == TT_PARAMRETURN)
495 bool noerror = FALSE;
497 if (alkind_isDependent (sRef_getAliasKind (fref)))
499 if (canLoseLocalReference (fref, loc))
509 ("Storage %qreachable from parameter is %s (should be %s)",
510 sRef_unparseOpt (fref),
511 alkind_unparse (sRef_getAliasKind (fref)),
512 alkind_unparse (sRef_getAliasKind (tref))),
515 sRef_showAliasInfo (fref);
518 else if (transferType == TT_LEAVETRANS)
523 ("Storage %qreachable from temporary reference is %s "
524 "at scope exit (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_GLOBRETURN)
538 ("Storage %qreachable from global is %s (should be %s)",
539 sRef_unparseOpt (fref),
540 alkind_unparse (sRef_getAliasKind (fref)),
541 alkind_unparse (sRef_getAliasKind (tref))),
544 sRef_showAliasInfo (fref);
547 else if (transferType == TT_FCNRETURN)
552 ("Storage %qreachable from return value is %s (should be %s)",
553 sRef_unparseOpt (fref),
554 alkind_unparse (sRef_getAliasKind (fref)),
555 alkind_unparse (sRef_getAliasKind (tref))),
558 sRef_showAliasInfo (fref);
561 else if (transferType == TT_GLOBINIT)
566 ("Storage %qreachable from initial value is %s (should be %s)",
567 sRef_unparseOpt (fref),
568 alkind_unparse (sRef_getAliasKind (fref)),
569 alkind_unparse (sRef_getAliasKind (tref))),
572 sRef_showAliasInfo (fref);
577 llcontbug (message ("Transfer type: %s",
578 transferType_unparse (transferType)));
583 ("Storage %qreachable from return value is %s (should be %s)",
584 sRef_unparseOpt (fref),
585 alkind_unparse (sRef_getAliasKind (fref)),
586 alkind_unparse (sRef_getAliasKind (tref))),
589 sRef_showAliasInfo (fref);
594 if (sRef_isDead (fref))
601 if (transferType == TT_PARAMRETURN)
606 ("Released storage %q reachable from parameter at return point",
607 sRef_unparse (fref)),
610 sRef_showStateInfo (fref);
614 else if (transferType == TT_LEAVETRANS)
618 message ("Released storage %q reachable from temporary "
619 "reference at scope exit",
620 sRef_unparse (fref)),
623 sRef_showStateInfo (fref);
627 else if (transferType == TT_GLOBRETURN)
631 message ("Released storage %q reachable from global",
632 sRef_unparse (fref)),
635 sRef_showStateInfo (fref);
639 else if (transferType == TT_FCNPASS)
643 message ("Released storage %q reachable from passed parameter",
644 sRef_unparse (fref)),
647 sRef_showStateInfo (fref);
655 message ("Released storage %q reachable from parameter",
656 sRef_unparse (fref)),
659 sRef_showStateInfo (fref);
667 && sRef_possiblyNull (fref)
668 && !sRef_perhapsNull (tref)
669 && ctype_isRealPointer (sRef_getType (tref))
670 && !usymtab_isGuarded (fref))
672 if (transferType == TT_FCNRETURN)
676 message ("%q storage %qderivable from return value: %s",
677 cstring_capitalize (sRef_nullMessage (fref)),
678 sRef_unparseOpt (fref),
679 exprNode_unparse (fexp)),
682 sRef_showNullInfo (fref);
683 sRef_setNullError (fref);
686 else if (transferType == TT_GLOBRETURN || transferType == TT_PARAMRETURN)
691 ("Function returns with %s storage derivable from %q %q",
692 sRef_nullMessage (fref),
693 cstring_makeLiteral ((transferType == TT_GLOBRETURN)
694 ? "global" : "parameter"),
695 sRef_unparse (fref)),
698 sRef_showNullInfo (fref);
699 sRef_setNullError (fref);
702 else if (transferType == TT_GLOBPASS)
706 message ("Function called with %s storage "
707 "derivable from global %q",
708 sRef_nullMessage (fref),
709 sRef_unparse (fref)),
712 sRef_showNullInfo (fref);
713 sRef_setNullError (fref);
716 else if (transferType == TT_FCNPASS)
720 message ("%q storage %qderivable from parameter %q",
721 cstring_capitalize (sRef_nullMessage (fref)),
722 sRef_unparseOpt (fref),
723 generateText (fexp, exprNode_undefined,
724 sRef_undefined, TT_FCNPASS)),
727 sRef_showNullInfo (fref);
728 sRef_setNullError (fref);
733 llassert (transferType == TT_DOASSIGN
734 || transferType == TT_GLOBINIT
735 || transferType == TT_LEAVETRANS);
739 if (sRef_isRelDef (tref)
740 || sRef_isPartial (tref)
741 || sRef_isAllocated (tref)
742 || sRef_isStateSpecial (tref))
744 /* should check fref is allocated? */
748 ct = ctype_realType (sRef_getType (fref));
750 if (!(sRef_isAnyDefined (fref)
751 || sRef_isPdefined (fref)
752 || sRef_isAllocated (fref)
753 || sRef_isStateUnknown (fref)))
755 if (transferType == TT_GLOBRETURN)
760 message ("Function returns with global %q not "
761 "completely defined%q",
762 sRef_unparse (sRef_getRootBase (fref)),
766 sRef_showStateInfo (fref);
767 sRef_setDefined (fref, loc);
770 else if (transferType == TT_GLOBPASS)
776 ("Function called with global %q not completely defined%q",
777 sRef_unparse (sRef_getRootBase (fref)),
781 sRef_showStateInfo (fref);
782 sRef_setDefined (fref, loc);
785 else if (transferType == TT_PARAMRETURN)
787 if (report && !topLevel
790 message ("Function returns storage %q reachable from parameter not "
791 "completely defined%q",
792 sRef_unparse (sRef_getRootBase (fref)),
796 sRef_showStateInfo (fref);
797 sRef_setDefined (fref, loc);
800 else if (transferType == TT_LEAVETRANS)
802 if (report && !topLevel
805 message ("Scope exits with storage %q reachable from "
806 "temporary reference not completely defined%q",
807 sRef_unparse (sRef_getRootBase (fref)),
811 sRef_showStateInfo (fref);
812 sRef_setDefined (fref, loc);
817 if (transferType != TT_DOASSIGN
818 && (!(sRef_isNew (fref) || sRef_isType (fref))))
822 if (sRef_isDead (fref))
826 message ("%s storage %qwas released: %q",
827 transferType_unparse (transferType),
828 sRef_unparseOpt (fref),
829 generateText (fexp, texp, tref, transferType)),
832 sRef_showStateInfo (fref);
840 ("%s storage %qnot completely defined%q: %q",
841 transferType_unparse (transferType),
842 sRef_unparseOpt (sRef_getRootBase (fref)),
844 generateText (fexp, texp, tref, transferType)),
847 sRef rb = sRef_getRootBase (fref);
848 sRef_showStateInfo (fref);
849 sRef_setDefinedComplete (rb, loc);
857 if (sRef_isAllocated (fref) && sRef_isValid (tref)
858 && (transferType == TT_DOASSIGN))
860 sRef_setAllocatedComplete (tref, loc);
869 if (ctype_isUnknown (ct))
873 else if (ctype_isPointer (ct))
875 ctype tct = ctype_realType (sRef_getType (tref));
877 if (sRef_isStateUnknown (fref))
883 if (ctype_isAP (tct) || ctype_isUnknown (tct))
885 sRef fptr = sRef_constructDeref (fref);
886 sRef tptr = sRef_constructDeref (tref);
888 return (checkCompletelyDefined (fexp, fptr, texp, tptr,
889 FALSE, inUnion, FALSE, loc,
890 transferType, depth + 1, report));
898 else if (ctype_isArray (ct))
902 else if (ctype_isStruct (ct))
904 ctype tct = ctype_realType (sRef_getType (tref));
906 if (ctype_match (ct, tct))
909 bool hasOneDefined = FALSE;
910 cstringSList badFields = cstringSList_undefined;
912 if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref))
917 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
919 sRefSet_realElements (sRef_derivedFields (fref), sr)
923 hasOneDefined = TRUE;
925 if (sRef_isField (sr))
927 cstring fieldname = sRef_getField (sr);
928 sRef fldref = sRef_makeField (tref, fieldname);
929 bool shouldCheck = !sRef_isRecursiveField (fldref);
935 (checkCompletelyDefined (fexp, sr, texp, fldref,
936 FALSE, inUnion, FALSE, loc,
937 transferType, depth + 1,
948 badFields = cstringSList_add (badFields,
952 } end_sRefSet_realElements;
954 else if (sRef_isAllocated (fref))
957 ** for structures, each field must be completely defined
960 uentryList fields = ctype_getFields (ct);
962 uentryList_elements (fields, ue)
965 cstring name = uentry_getRealName (ue);
966 sRef ffield = sRef_makeField (fref, name);
967 sRef tfield = sRef_makeField (tref, name);
968 bool shouldCheck = !sRef_isRecursiveField (tfield);
976 thisField = ynm_toBoolRelaxed
977 (checkCompletelyDefined (fexp, ffield, texp, tfield,
978 FALSE, inUnion, FALSE,
986 badFields = cstringSList_add (badFields, uentry_rawName (ue));
990 hasOneDefined = TRUE;
992 } end_uentryList_elements;
999 if (!isOk && (!inUnion || hasOneDefined))
1001 if (transferType == TT_GLOBRETURN)
1005 message ("Global storage %q contains %d undefined field%p "
1006 "when call returns: %q",
1007 sRef_unparse (fref),
1008 cstringSList_size (badFields),
1009 cstringSList_unparseAbbrev (badFields)),
1012 sRef_setDefined (fref, loc);
1015 else if (transferType == TT_GLOBPASS)
1019 message ("Global storage %q contains %d undefined field%p "
1021 sRef_unparse (fref),
1022 cstringSList_size (badFields),
1023 cstringSList_unparseAbbrev (badFields)),
1026 sRef_setDefined (fref, loc);
1029 else if (transferType == TT_PARAMRETURN)
1033 message ("Storage %qreachable from parameter "
1034 "contains %d undefined field%p: %q",
1035 sRef_unparseOpt (fref),
1036 cstringSList_size (badFields),
1037 cstringSList_unparseAbbrev (badFields)),
1040 sRef_setDefined (fref, loc);
1043 else if (transferType == TT_LEAVETRANS)
1051 message ("%s storage %qcontains %d undefined field%p: %q",
1052 transferType_unparse (transferType),
1053 sRef_unparseOpt (fref),
1054 cstringSList_size (badFields),
1055 cstringSList_unparseAbbrev (badFields)),
1058 sRef_setDefined (fref, loc);
1063 cstringSList_free (badFields);
1069 return (ynm_fromBool (hasOneDefined));
1078 return (ynm_fromBool (!report || isOk));
1086 else if (ctype_isUnion (ct))
1088 if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref))
1094 ctype tct = ctype_realType (sRef_getType (tref));
1096 if (ctype_isKnown (tct) && ctype_match (ct, tct))
1098 cstringSList goodFields = cstringSList_new ();
1100 int nelements = sRefSet_size (sRef_derivedFields (fref));
1103 ** for unions, at least one field must be completely defined
1106 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
1111 sRefSet_realElements (sRef_derivedFields (fref), sr)
1115 if (sRef_isField (sr))
1117 sRef fldref = sRef_makeField (tref, sRef_getField (sr));
1119 thisField = ynm_toBoolStrict
1120 (checkCompletelyDefined
1121 (fexp, sr, texp, fldref, FALSE, inUnion,
1122 (nelements > 1 ? TRUE : FALSE),
1123 loc, transferType, depth + 1, FALSE));
1127 goodFields = cstringSList_add
1128 (goodFields, sRef_getField (sr));
1131 } end_sRefSet_realElements;
1133 if (cstringSList_empty (goodFields)
1135 && context_getFlag (FLG_UNIONDEF))
1139 if (transferType == TT_PARAMRETURN)
1143 message ("Union %q reachable from parameter has "
1145 sRef_unparse (fref)),
1148 else if (transferType == TT_LEAVETRANS)
1152 message ("Union %q has no defined field at scope exit",
1153 sRef_unparse (fref)),
1156 else if (transferType == TT_DOASSIGN
1157 || transferType == TT_FIELDASSIGN
1158 || transferType == TT_GLOBINIT)
1166 message ("%s union %q has no defined field",
1167 transferType_unparse (transferType),
1168 sRef_unparse (fref)),
1175 cstringSList_free (goodFields);
1176 return ynm_fromBool (!report || isOk);
1189 ** fref is being free'd
1193 DSC_GLOB, DSC_LOCAL, DSC_PARAM, DSC_STRUCT
1196 static /*@observer@*/ cstring dscCode_unparse (dscCode desc) /*@*/
1201 return cstring_makeLiteralTemp ("killed global");
1203 return cstring_makeLiteralTemp ("variable declared in this scope");
1205 return cstring_makeLiteralTemp ("released storage");
1207 return cstring_makeLiteralTemp ("released structure parameter");
1214 checkCompletelyDestroyed (exprNode p_fexp, sRef p_fref, bool p_topLevel,
1215 fileloc p_loc, int p_depth, dscCode p_desc);
1217 bool checkGlobalDestroyed (sRef fref, fileloc loc)
1219 return (checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1223 void checkLocalDestroyed (sRef fref, fileloc loc)
1225 if (sRef_isObserver (fref) || sRef_isExposed (fref)
1226 || sRef_isPartial (fref))
1232 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1237 void checkStructDestroyed (sRef fref, fileloc loc)
1239 if (sRef_isObserver (fref) || sRef_isExposed (fref)
1240 || sRef_isPartial (fref))
1246 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE, loc, 0, DSC_STRUCT);
1251 checkCompletelyDestroyed (exprNode fexp, sRef fref, bool topLevel,
1252 fileloc loc, int depth,
1257 if (depth > MAXDEPTH)
1259 llquietbug (message ("checkCompletelyDestroyed: too deep: %s / %q",
1260 exprNode_unparse (fexp),
1261 sRef_unparseFull (fref)));
1265 if (!sRef_isKnown (fref)) return TRUE;
1266 if (usymtab_isProbableNull (fref)) return TRUE;
1267 if (!context_getFlag (FLG_COMPDESTROY)) return TRUE;
1268 if (!context_getFlag (FLG_MUSTFREE)) return TRUE;
1270 ct = ctype_realType (sRef_getType (fref));
1276 if (sRef_isFresh (fref) || sRef_isOnly (fref))
1280 if (sRef_isDead (fref)
1281 || sRef_isUnuseable (fref)
1282 || sRef_definitelyNull (fref)
1283 || sRef_isObserver (fref)
1284 || sRef_isExposed (fref))
1292 if (sRef_isPossiblyDead (fref) || sRef_isRelDef (fref))
1294 if (exprNode_isDefined (fexp))
1297 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1298 message ("Only storage %q (type %s) derived from %s "
1299 "may not have been released: %s",
1300 sRef_unparse (fref),
1301 ctype_unparse (sRef_getType (fref)),
1302 dscCode_unparse (desc),
1303 exprNode_unparse (fexp)),
1309 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1311 ("Only storage %q (type %s) derived from %s "
1312 "may not have been released",
1313 sRef_unparse (fref),
1314 ctype_unparse (sRef_getType (fref)),
1315 dscCode_unparse (desc)),
1319 sRef_kill (fref, loc); /* prevent further errors */
1323 if (sRef_isStateUndefined (fref))
1329 if (exprNode_isDefined (fexp))
1333 message ("Only storage %q (type %s) derived from %s "
1334 "is not released (memory leak): %s",
1335 sRef_unparse (fref),
1336 ctype_unparse (sRef_getType (fref)),
1337 dscCode_unparse (desc),
1338 exprNode_unparse (fexp)),
1345 message ("Only storage %q (type %s) derived from %s "
1346 "is not released (memory leak)",
1347 sRef_unparse (fref),
1348 ctype_unparse (sRef_getType (fref)),
1349 dscCode_unparse (desc)),
1358 if (sRef_isAnyDefined (fref) || sRef_isDead (fref)
1359 || (sRef_isPdefined (fref)
1360 && sRefSet_isEmpty (sRef_derivedFields (fref))))
1366 if (ctype_isPointer (ct))
1368 sRef fptr = sRef_constructDeadDeref (fref);
1369 bool res = checkCompletelyDestroyed (fexp, fptr, FALSE, loc,
1374 else if (ctype_isArray (ct))
1376 if ((sRef_isStateUnknown (fref) || sRef_isAllocated (fref))
1377 && !sRef_hasDerived (fref))
1380 ** Bogosity necessary to prevent infinite depth.
1387 sRef farr = sRef_constructDeadDeref (fref);
1389 return (checkCompletelyDestroyed (fexp, farr, FALSE, loc,
1393 else if (ctype_isStruct (ct))
1396 ** for structures, each field must be completely destroyed
1400 uentryList fields = ctype_getFields (ct);
1402 if (depth >= MAXDEPTH)
1404 llquietbug (message ("checkCompletelyDestroyed (fields): too deep: %s / %q",
1405 exprNode_unparse (fexp),
1406 sRef_unparseFull (fref)));
1412 uentryList_elements (fields, ue)
1414 sRef field = sRef_makeField (fref, uentry_rawName (ue));
1417 ** note order of && operands --- want to report multiple errors
1420 isOk = (checkCompletelyDestroyed (fexp, field, FALSE, loc,
1423 } end_uentryList_elements;
1435 checkReturnTransfer (exprNode fexp, uentry rval)
1437 sRef uref = uentry_getSref (rval);
1438 sRef rref = sRef_makeNew (sRef_getType (uref), uref, cstring_undefined);
1440 if (sRef_isStateSpecial (rref))
1442 uentry fcn = context_getHeader ();
1443 sRef fref = exprNode_getSref (fexp);
1444 specialClauses clauses = uentry_getSpecialClauses (fcn);
1446 specialClauses_postElements (clauses, cl)
1448 sRefSet refs = specialClause_getRefs (cl);
1449 sRefTest tst = specialClause_getPostTestFunction (cl);
1450 sRefMod modf = specialClause_getReturnEffectFunction (cl);
1452 sRefSet_elements (refs, el)
1454 sRef base = sRef_getRootBase (el);
1456 if (sRef_isResult (base))
1458 sRef sr = sRef_fixBase (el, fref);
1460 if (tst != NULL && !(tst (sr)))
1463 (specialClause_postErrorCode (cl),
1464 message ("%s storage %q corresponds to "
1465 "storage listed in %q clause: %s",
1466 specialClause_postErrorString (cl, sr),
1468 specialClause_unparseKind (cl),
1469 exprNode_unparse (fexp)),
1470 exprNode_loc (fexp)))
1472 sRefShower ss = specialClause_getPostTestShower (cl);
1483 modf (sr, exprNode_loc (fexp));
1489 ** Non-results are checked in exit scope.
1492 } end_sRefSet_elements ;
1493 } end_specialClauses_postElements ;
1495 (void) checkTransfer (fexp, fref,
1496 exprNode_undefined, rref,
1497 exprNode_loc (fexp), TT_FCNRETURN);
1501 if (ctype_isRealSU (exprNode_getType (fexp)))
1503 sRef fref = exprNode_getSref (fexp);
1505 checkStructTransfer (exprNode_undefined, rref,
1507 exprNode_loc (fexp),
1512 (void) checkTransfer (fexp, exprNode_getSref (fexp),
1513 exprNode_undefined, rref,
1514 exprNode_loc (fexp), TT_FCNRETURN);
1520 checkPassSpecialClauses (uentry ue, exprNode fexp, sRef fref, int argno)
1522 specialClauses clauses = uentry_getSpecialClauses (ue);
1524 DPRINTF (("Check pass special: %s / %s",
1525 exprNode_unparse (fexp), sRef_unparseFull (fref)));
1527 specialClauses_preElements (clauses, cl)
1529 sRefSet refs = specialClause_getRefs (cl);
1530 sRefTest tst = specialClause_getPreTestFunction (cl);
1531 sRefMod modf = specialClause_getEffectFunction (cl);
1533 sRefSet_elements (refs, el)
1535 sRef base = sRef_getRootBase (el);
1537 if (sRef_isResult (base))
1539 ; /* nothing to check before */
1541 else if (sRef_isParam (base))
1543 if (sRef_getParam (base) == argno - 1)
1547 DPRINTF (("Fix base: %s / %s",
1548 sRef_unparseFull (el),
1549 sRef_unparseFull (fref)));
1551 sb = sRef_fixBase (el, fref);
1553 if (tst != NULL && !(tst(sb)))
1556 (specialClause_preErrorCode (cl),
1557 message ("%s storage %qcorresponds to "
1558 "storage listed in %q clause of "
1559 "called function: %s",
1560 specialClause_preErrorString (cl, sb),
1561 sRef_unparseOpt (sb),
1562 specialClause_unparseKind (cl),
1563 exprNode_unparse (fexp)),
1564 exprNode_loc (fexp));
1569 DPRINTF (("Fixing: %s", sRef_unparseFull (sb)));
1570 modf (sb, exprNode_loc (fexp));
1571 DPRINTF (("==> %s", sRef_unparseFull (sb)));
1579 } end_sRefSet_elements ;
1580 } end_specialClauses_preElements ;
1582 DPRINTF (("After: %s", sRef_unparseFull (fref)));
1586 ** should not modify arg
1590 checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
1591 /*@dependent@*/ exprNode fcn, int argno, int totargs)
1593 sRef tref = uentry_getSref (arg);
1594 sRef fref = exprNode_getSref (fexp);
1596 bool isPartial = FALSE;
1597 bool isImpOut = FALSE;
1598 ctype ct = uentry_getType (arg);
1600 DPRINTF (("Check pass: %s -> %s",
1601 sRef_unparseFull (fref),
1602 sRef_unparseFull (tref)));
1606 atNumArgs = totargs;
1608 if (ctype_isElips (ct))
1613 if (!ctype_isElips (ct) &&
1614 (ctype_isVoidPointer (ct) && uentry_isOut (arg) && sRef_isOnly (tref)))
1616 if (ctype_isRealAP (ct))
1618 if (sRef_aliasCheckSimplePred (sRef_isDead, fref))
1622 message ("Dead storage %qpassed as out parameter: %s",
1623 sRef_unparseOpt (fref),
1624 exprNode_unparse (fexp)),
1625 exprNode_loc (fexp)))
1627 if (sRef_isDead (fref))
1629 sRef_showStateInfo (fref);
1633 sRef_setAllocated (fref, exprNode_loc (fexp));
1635 else if (context_getFlag (FLG_STRICTUSERELEASED)
1636 && sRef_aliasCheckSimplePred (sRef_isPossiblyDead, fref))
1639 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1640 message ("Possibly dead storage %qpassed as out parameter: %s",
1641 sRef_unparseOpt (fref),
1642 exprNode_unparse (fexp)),
1643 exprNode_loc (fexp)))
1645 if (sRef_isPossiblyDead (fref))
1647 sRef_showStateInfo (fref);
1651 sRef_setAllocated (fref, exprNode_loc (fexp));
1653 else if (sRef_aliasCheckSimplePred (sRef_isStateUndefined, fref)
1654 || sRef_aliasCheckSimplePred (sRef_isUnuseable, fref))
1658 message ("Unallocated storage %qpassed as out parameter: %s",
1659 sRef_unparseOpt (fref),
1660 exprNode_unparse (fexp)),
1661 exprNode_loc (fexp));
1663 sRef_setAllocated (fref, exprNode_loc (fexp));
1671 (void) checkCompletelyDestroyed (fexp, fref, TRUE, exprNode_loc (fexp),
1674 /* make it defined now, so checkTransfer is okay */
1675 sRef_setDefined (fref, exprNode_loc (fexp));
1677 else if (uentry_isOut (arg))
1679 if (ctype_isRealAP (ct)
1680 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1684 message ("Unallocated storage %qpassed as out parameter: %s",
1685 sRef_unparseOpt (fref),
1686 exprNode_unparse (fexp)),
1687 exprNode_loc (fexp));
1688 sRef_setAllocated (fref, exprNode_loc (fexp));
1692 else if (uentry_isPartial (arg))
1694 if (ctype_isRealAP (ct)
1695 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1699 message ("Unallocated storage %qpassed as partial parameter: %s",
1700 sRef_unparseOpt (fref),
1701 exprNode_unparse (fexp)),
1702 exprNode_loc (fexp));
1703 sRef_setAllocated (fref, exprNode_loc (fexp));
1707 else if (uentry_isStateSpecial (arg))
1709 uentry ue = exprNode_getUentry (fcn);
1711 if (ctype_isRealAP (ct)
1712 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1716 message ("Unallocated storage %qpassed as special parameter: %s",
1717 sRef_unparseOpt (fref),
1718 exprNode_unparse (fexp)),
1719 exprNode_loc (fexp));
1720 sRef_setAllocated (fref, exprNode_loc (fexp));
1723 if (uentry_hasSpecialClauses (ue))
1725 checkPassSpecialClauses (ue, fexp, fref, argno);
1730 else if (sRef_isStateDefined (tref))
1732 exprNode_checkUseParam (fexp);
1736 if (isSpec || (!context_getFlag (FLG_IMPOUTS)))
1738 exprNode_checkUseParam (fexp);
1742 if (!sRef_isMacroParamRef (fref)
1743 && (ctype_isRealAP (ct)))
1745 if (sRef_isAddress (fref))
1747 if (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref))
1752 ("Unallocated address %qpassed as implicit "
1753 "out parameter: %s",
1754 sRef_unparseOpt (fref),
1755 exprNode_unparse (fexp)),
1756 exprNode_loc (fexp));
1757 sRef_setAllocated (fref, exprNode_loc (fexp));
1761 /* yes, I really mean this! */
1762 tref = sRef_copy (tref);
1763 sRef_setAllocated (tref, exprNode_loc (fexp));
1770 exprNode_checkUseParam (fexp);
1775 if (sRef_isNew (fref))
1777 alkind tkind = sRef_getAliasKind (tref);
1779 if ((sRef_isFresh (fref) || sRef_isOnly (fref))
1780 && !alkind_isOnly (tkind)
1781 && !alkind_isKeep (tkind)
1782 && !alkind_isOwned (tkind)
1783 && !alkind_isError (tkind)
1784 && !uentry_isReturned (arg))
1789 message ("New fresh storage %qpassed as %s (not released): %s",
1790 sRef_unparseOpt (fref),
1791 alkind_unparse (sRef_getAliasKind (tref)),
1792 exprNode_unparse (fexp)),
1793 exprNode_loc (fexp));
1797 if (sRef_isNewRef (fref) && !sRef_isKillRef (tref))
1799 alkind ak = sRef_getAliasKind (tref);
1801 if (!alkind_isError (ak))
1805 message ("New reference %qpassed as %s (not released): %s",
1806 sRef_unparseOpt (fref),
1807 alkind_unparse (sRef_getAliasKind (tref)),
1808 exprNode_unparse (fexp)),
1809 exprNode_loc (fexp));
1815 (void) checkTransfer (fexp, exprNode_getSref (fexp),
1816 exprNode_undefined, tref,
1817 exprNode_loc (fexp), TT_FCNPASS);
1820 fref = exprNode_getSref (fexp);
1822 if (isOut && !sRef_isDead (fref) && !sRef_isPossiblyDead (fref))
1826 if (ctype_isRealAP (sRef_getType (fref)))
1828 base = sRef_makePointer (fref);
1837 exprNode_checkMSet (fexp, base);
1841 exprNode_checkSet (fexp, base);
1844 if (sRef_isValid (base))
1848 sRef_clearDerived (base);
1849 sRef_setDefined (base, exprNode_loc (fexp));
1850 usymtab_clearAlias (base);
1851 sRef_setNullUnknown (base, exprNode_loc (fexp));
1857 if (sRef_isValid (fref))
1859 sRef_setPartial (fref, exprNode_loc (fexp));
1863 atFunction = exprNode_undefined;
1867 /* need to fixup here: derived refs could be bogus */
1868 /* (better to change sRef to not add derivs for "protected" ref) */
1870 uentry_fixupSref (arg);
1874 DPRINTF (("Check pass: ==> %s",
1875 sRef_unparseFull (fref)));
1879 checkGlobReturn (uentry glob)
1881 sRef_protectDerivs ();
1882 checkGlobTrans (glob, TT_GLOBRETURN);
1883 sRef_clearProtectDerivs ();
1886 void checkParamReturn (uentry actual)
1888 checkLeaveTrans (actual, TT_PARAMRETURN);
1891 void checkLoseRef (uentry actual)
1893 checkLeaveTrans (actual, TT_LEAVETRANS);
1897 checkLeaveTrans (uentry actual, transferKind transferType)
1899 sRef aref = uentry_getSref (actual);
1900 sRef origref = uentry_getOrigSref (actual);
1902 if (transferType == TT_PARAMRETURN
1903 && (sRef_isKeep (origref) || sRef_isOnly (origref)
1904 || sRef_isOwned (origref)))
1906 /* caller cannot use, nothing to check */
1910 if (sRef_isNSLocalVar (origref))
1916 (void) checkCompletelyDefined (exprNode_undefined, aref,
1917 exprNode_undefined, origref,
1919 g_currentloc, transferType,
1926 checkGlobTrans (uentry glob, transferKind type)
1928 sRef eref = uentry_getOrigSref (glob);
1930 (void) checkCompletelyDefined (exprNode_undefined, uentry_getSref (glob),
1931 exprNode_undefined, eref,
1933 g_currentloc, type, 0, TRUE);
1937 ** For lhs of assignment, alias kind is set from basic type.
1942 fixAssignLhs (sRef s)
1944 sRef_resetStateComplete (s);
1947 static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srhs,
1951 ctype st = ctype_realType (sRef_getType (srhs));
1953 if (ctype_isSU (st) && ctype_isRealSU (sRef_getType (slhs))
1954 && ctype_match (sRef_getType (slhs), st))
1956 if (tt == TT_DOASSIGN && sRef_isStateDefined (srhs))
1958 sRef_setDefinedComplete (slhs, loc);
1961 if (sRef_isDependent (slhs)
1962 || sRef_isObserver (slhs)
1963 || sRef_isExposed (slhs))
1969 if (sRef_isLocalVar (slhs)
1970 && sRef_isGlobal (sRef_getRootBase (srhs)))
1972 sRef_setDependent (slhs, exprNode_loc (lhs));
1976 if (ctype_isUnion (st))
1978 sRef_setDefState (slhs, sRef_getDefState (srhs),
1979 exprNode_loc (lhs));
1981 sRefSet_realElements (sRef_derivedFields (srhs), sr)
1983 if (sRef_isField (sr))
1985 cstring fieldname = sRef_getField (sr);
1986 sRef lfld = sRef_makeField (slhs, fieldname);
1988 (void) checkTransfer (rhs, sr, lhs, lfld,
1989 exprNode_loc (lhs), tt);
1991 } end_sRefSet_realElements ;
1995 uentryList fields = ctype_getFields (st);
1997 uentryList_elements (fields, field)
1999 sRef rfld = sRef_makeField (srhs, uentry_rawName (field));
2000 sRef lfld = sRef_makeField (slhs, uentry_rawName (field));
2001 (void) checkTransfer (rhs, rfld, lhs, lfld, exprNode_loc (lhs), tt);
2002 } end_uentryList_elements ;
2005 if (sRef_isOnly (srhs))
2007 sRef_setKeptComplete (srhs, loc);
2015 checkInitTransfer (exprNode lhs, exprNode rhs)
2017 sRef slhs = exprNode_getSref (lhs);
2019 if (sRef_isGlobal (slhs) || (!sRef_isCvar (slhs)))
2021 (void) checkTransfer (rhs, exprNode_getSref (rhs),
2022 lhs, slhs, exprNode_loc (rhs), TT_GLOBINIT);
2026 checkAssignTransfer (lhs, rhs);
2031 checkAssignTransfer (exprNode lhs, exprNode rhs)
2033 sRef slhs = exprNode_getSref (lhs);
2034 sRef srhs = exprNode_getSref (rhs);
2035 sRef base = sRef_getBaseSafe (slhs);
2037 struct _bbufinfo bs;
2039 DPRINTF (("Check assign: %s = %s", exprNode_unparse (lhs),
2040 exprNode_unparse (rhs)));
2041 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2042 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2044 if (ctype_isRealSU (sRef_getType (srhs)))
2046 checkStructTransfer (lhs, slhs, rhs, srhs, exprNode_loc (lhs), TT_FIELDASSIGN);
2050 (void) checkTransfer (rhs, srhs, lhs, slhs,
2051 exprNode_loc (lhs), TT_DOASSIGN);
2054 if (sRef_isConst (srhs) && sRef_isLocalState (srhs))
2056 /* constants can match anything (e.g., NULL) */
2057 sRef_setAliasKind (slhs, AK_ERROR, fileloc_undefined);
2060 if (sRef_isValid (base) && sRef_isStateDefined (base))
2062 sRef_setPdefined (base, g_currentloc);
2065 if (sRef_isPartial (srhs))
2067 sRef_setPartial (slhs, exprNode_loc (rhs));
2071 ns = sRef_getNullState (srhs);
2073 if (nstate_possiblyNull (ns))
2075 if (usymtab_isGuarded (srhs))
2081 sRef_setNullStateInnerComplete (slhs, ns, exprNode_loc (rhs));
2083 if (sRef_isExposed (srhs) || sRef_isObserver (srhs))
2085 sRef_setExKind (slhs, sRef_getExKind (srhs), exprNode_loc (rhs));
2088 /* We put the function to transfer NT states */
2089 bs = sRef_getNullTerminatedState (srhs);
2090 sRef_setNullTerminatedStateInnerComplete (slhs, bs, exprNode_loc (rhs));
2091 DPRINTF (("Done transfer: %s", sRef_unparseFull (slhs)));
2095 checkTransferNullAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2096 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2097 fileloc loc, transferKind transferType)
2099 alkind tkind = sRef_getAliasKind (tref);
2100 ctype ttyp = ctype_realType (sRef_getType (tref));
2102 if (ctype_isUnknown (ttyp))
2104 ttyp = exprNode_getType (texp);
2106 if (ctype_isUnknown (ttyp))
2108 ttyp = exprNode_getType (fexp);
2110 if (ctype_isUnknown (ttyp))
2112 ttyp = sRef_getType (fref);
2117 if (ctype_isFunction (ttyp) && (transferType == TT_FCNRETURN))
2119 ttyp = ctype_returnValue (ttyp);
2123 ** check for null (don't need to check aliases??)
2126 if (sRef_possiblyNull (fref)
2127 && !usymtab_isGuarded (fref)
2128 && ctype_isRealAP (ttyp))
2130 if (!alkind_isLocal (tkind) && !alkind_isFresh (tkind)
2131 && !sRef_perhapsNull (tref)
2132 && !(transferType == TT_DOASSIGN))
2134 if (transferType == TT_GLOBINIT)
2138 message ("%s %q initialized to %s value: %q",
2139 sRef_getScopeName (tref),
2140 sRef_unparse (tref),
2141 sRef_nullMessage (fref),
2142 generateText (fexp, texp, tref, transferType)),
2145 sRef_showNullInfo (fref);
2146 sRef_setNullError (tref);
2152 ((transferType == TT_FCNPASS) ? FLG_NULLPASS : FLG_NULLRET,
2153 message ("%q storage %q%s: %q",
2154 cstring_capitalize (sRef_nullMessage (fref)),
2155 sRef_unparseOpt (fref),
2156 transferNullMessage (transferType),
2157 generateText (fexp, texp, tref, transferType)),
2160 sRef_showNullInfo (fref);
2161 sRef_setNullError (fref);
2174 checkTransferAssignAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2175 sRef tref, exprNode texp, bool tfix,
2176 fileloc loc, transferKind transferType)
2178 alkind tkind = sRef_getAliasKind (tref);
2181 ** Assignment to same --- no errors, or state changes.
2182 ** This can happen when returned params are used.
2185 if (sRef_sameName (fref, tref))
2187 sRef_copyState (tref, fref);
2191 if ((alkind_isOnly (tkind) || alkind_isFresh (tkind)
2192 || alkind_isNewRef (tkind) || alkind_isOwned (tkind))
2193 && !(sRef_isDead (tref)
2194 || sRef_isStateUndefined (tref)
2195 || sRef_isUnuseable (tref)
2196 || sRef_isPartial (tref)
2197 || sRef_definitelyNull (tref)
2198 || sRef_isStackAllocated (tref)
2199 || sRef_isAllocIndexRef (tref))
2200 && !(sRef_same (fref, tref)) /* okay to assign to self (returned params) */
2201 && !(usymtab_isProbableNull (tref)))
2203 if (context_getFlag (FLG_MUSTFREE))
2205 if (canLoseReference (tref, loc))
2211 if (sRef_hasLastReference (tref))
2215 message ("Last reference %q to %s storage %qnot released "
2216 "before assignment: %q",
2217 sRef_unparse (tref),
2218 alkind_unparse (tkind),
2219 sRef_unparseOpt (sRef_getAliasInfoRef (tref)),
2220 generateText (fexp, texp, tref, transferType)),
2223 sRef_showRefLost (tref);
2228 if (context_inGlobalScope ())
2230 /* no errors for static initializations */
2235 ** don't report this error for a[i], since it could
2236 ** be a new element.
2239 if (alkind_isNewRef (tkind))
2244 ("%q %qnot released before assignment: %q",
2246 (alkind_isKillRef (sRef_getOrigAliasKind (tref))
2247 ? "Kill reference parameter" : "New reference"),
2248 sRef_unparseOpt (tref),
2249 generateText (fexp, texp, tref, transferType)),
2252 sRef_showAliasInfo (tref);
2253 sRef_setAliasKind (tref, AK_ERROR, loc);
2257 (!(sRef_isUnknownArrayFetch (tref)
2258 && !context_getFlag (FLG_STRICTDESTROY))
2259 && !sRef_isUnionField (tref)
2260 && !sRef_isRelDef (tref)
2264 ("%s storage %qnot released before assignment: %q",
2265 alkind_capName (tkind),
2266 sRef_unparseOpt (tref),
2267 generateText (fexp, texp, tref, transferType)),
2270 sRef_showAliasInfo (tref);
2282 fixAssignLhs (tref);
2284 if (sRef_isRefCounted (tref)) /* tkind might not be correct now */
2286 if (sRef_isNewRef (fref))
2288 sRef_setAliasKind (tref, AK_NEWREF, loc);
2290 else if (sRef_isConst (fref))
2292 /* for now, constants are not ref counted */
2293 sRef_setAliasKind (tref, AK_ERROR, loc);
2300 if (!sRef_isNSLocalVar (tref)
2301 && sRef_isRefCounted (fref)
2302 && sRef_isStateDefined (fref))
2306 message ("New reference %qto reference counted storage: %q",
2307 sRef_unparseOpt (tref),
2308 generateText (fexp, texp, tref, transferType)),
2314 ** Not for structures and unions, since assignments copy.
2317 if (sRef_isStack (fref)
2318 && !ctype_isSU (ctype_realType (sRef_getType (fref))))
2320 sRef_setAliasKindComplete (tref, AK_STACK, loc);
2323 if (sRef_isNSLocalVar (tref)
2324 && !sRef_isOwned (tref) /*< should only apply to static >*/
2325 && ctype_isMutable (sRef_getType (tref)))
2327 if (sRef_isOnly (fref) && sRef_isNew (fref))
2331 sRef_setFresh (tref, loc);
2338 ** requires sRef_isOnly (fref)
2342 checkOnlyTransferAux (sRef fref, exprNode fexp, bool ffix,
2343 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2344 fileloc loc, transferKind transferType)
2346 alkind tkind = sRef_getAliasKind (tref);
2348 if (sRef_isExposed (tref) || sRef_isObserver (tref))
2350 if (transferType == TT_FCNRETURN && sRef_isNew (fref)
2351 && !alkind_isError (tkind))
2355 message ("Only storage %q%q (will not be released): %q",
2356 sRef_unparseOpt (fref),
2357 transferErrorMessage (transferType, tkind),
2358 generateText (fexp, texp, tref, transferType)),
2361 sRef_showAliasInfo (fref);
2365 /* no errors for exposed transfers (is this good enough?) */
2367 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind) || alkind_isOwned (tkind))
2371 else if ((transferType == TT_FCNPASS)
2372 && (alkind_isUnknown (tkind)
2373 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2375 if (sRef_isFresh (fref)
2376 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2378 if (!ffix) sRef_setAliasKind (fref, AK_UNKNOWN, loc);
2381 else if (alkind_isLocal (tkind)
2382 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2384 if ((transferType == TT_DOASSIGN)
2385 && sRef_isNew (fref)
2386 && sRef_isOnly (fref))
2390 if (alkind_isUnknown (tkind)
2391 && sRef_isGlobal (sRef_getRootBase (tref)))
2394 (FLG_ONLYUNQGLOBALTRANS,
2395 message ("Only storage %q%q: %q",
2396 sRef_unparseOpt (fref),
2397 transferErrorMessage (transferType, tkind),
2398 generateText (fexp, texp, tref, transferType)),
2401 sRef_showAliasInfo (fref);
2402 sRef_setAliasKind (tref, AK_ERROR, loc);
2407 if (!error && !ffix)
2409 sRef_setFresh (tref, loc);
2414 if (alkind_isLocal (tkind))
2416 if (sRef_sameName (tref, fref))
2418 ; /* don't set this --- corresponds to return transfer */
2423 ** Don't set local to dependent. Error will
2424 ** be detected through aliasing. Except for
2428 if (!tfix && sRef_isThroughArrayFetch (fref)
2429 && context_getFlag (FLG_DEPARRAYS))
2431 sRef_setDependent (tref, loc);
2439 message ("Only storage %q%q: %q",
2440 sRef_unparseOpt (fref),
2441 transferErrorMessage (transferType, tkind),
2442 generateText (fexp, texp, tref, transferType)),
2445 sRef_showAliasInfo (fref);
2452 if (alkind_isError (tkind)
2453 || (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT)))
2455 flagcode_recordSuppressed (FLG_ONLYTRANS);
2459 if ((alkind_isKept (tkind) || alkind_isStack (tkind)
2460 || alkind_isDependent (tkind))
2461 && sRef_isNSLocalVar (tref))
2469 message ("Only storage %q%q: %q",
2470 sRef_unparseOpt (fref),
2471 transferErrorMessage (transferType, tkind),
2472 generateText (fexp, texp, tref, transferType)),
2475 sRef_showAliasInfo (fref);
2480 if (transferType == TT_DOASSIGN)
2483 ** alias kind unknown to suppress future messages
2486 if (!ffix && sRef_isNSLocalVar (sRef_getRootBase (fref)))
2488 sRef_clearAliasKind (fref);
2495 ** ??? same as checkOnly ?
2499 checkOwnedTransferAux (sRef fref, exprNode fexp, bool ffix,
2500 sRef tref, exprNode texp, bool tfix,
2501 fileloc loc, transferKind transferType)
2503 alkind tkind = sRef_getAliasKind (tref);
2505 if (sRef_isExposed (tref) || sRef_isObserver (tref))
2507 if (transferType == TT_FCNRETURN && sRef_isNew (fref))
2511 message ("Owned storage %q%q (will not be released): %q",
2512 sRef_unparseOpt (fref),
2513 transferErrorMessage (transferType, tkind),
2514 generateText (fexp, texp, tref, transferType)),
2517 sRef_showAliasInfo (fref);
2521 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind)
2522 || alkind_isDependent (tkind)
2523 || alkind_isOwned (tkind))
2527 else if (alkind_isLocal (tkind)
2528 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2530 if ((transferType == TT_DOASSIGN)
2531 && sRef_isNew (fref) && sRef_isOnly (fref))
2535 sRef_setFresh (tref, loc);
2542 else if ((transferType == TT_FCNPASS)
2543 && (alkind_isUnknown (tkind)
2544 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2546 if (sRef_isFresh (fref)
2547 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2549 if (!ffix) { sRef_clearAliasKind (fref); }
2554 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2556 flagcode_recordSuppressed (FLG_OWNEDTRANS);
2560 if (alkind_isKept (tkind) && sRef_isNSLocalVar (tref))
2568 message ("Owned storage %q%q: %q",
2569 sRef_unparseOpt (fref),
2570 transferErrorMessage (transferType, tkind),
2571 generateText (fexp, texp, tref, transferType)),
2576 if (transferType == TT_DOASSIGN)
2579 ** alias kind unknown to suppress future messages
2582 if (!ffix) { sRef_clearAliasKind (fref); }
2588 checkFreshTransferAux (sRef fref, exprNode fexp, bool ffix,
2589 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2590 fileloc loc, transferKind transferType)
2592 alkind tkind = sRef_getAliasKind (tref);
2595 ** error to return fresh as non-only
2598 if (transferType == TT_FCNRETURN
2599 && !(alkind_isOnly (tkind) || alkind_isNewRef (tkind)))
2601 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2603 flagcode_recordSuppressed (FLG_NEWREFTRANS);
2607 if (alkind_isError (tkind))
2611 sRef_killComplete (fref, loc);
2614 else if (alkind_isRefCounted (tkind))
2619 ("New reference returned without newref qualifier: %q",
2620 generateText (fexp, texp, tref, transferType)),
2623 sRef_showAliasInfo (fref);
2624 sRef_killComplete (fref, loc);
2631 message ("Fresh storage %q (should be only): %q",
2632 transferErrorMessage (transferType, tkind),
2633 generateText (fexp, texp, tref, transferType)),
2636 sRef_showAliasInfo (fref);
2637 sRef_killComplete (fref, loc);
2644 ** Okay to assign fresh to only, shared or unqualified.
2646 ** should generate other errors?
2649 if (alkind_isOnly (tkind))
2651 if (transferType == TT_DOASSIGN && !sRef_isGlobal (tref))
2655 if (!sRef_isNSLocalVar (tref))
2657 sRef_setKeptComplete (fref, loc);
2663 if (sRef_isConst (fref))
2671 sRef_killComplete (fref, loc);
2676 else if (alkind_isOwned (tkind))
2680 sRef_setDependentComplete (fref, loc);
2683 else if (alkind_isRefCounted (tkind)
2684 && (transferType == TT_FCNRETURN) && sRef_isFresh (fref))
2688 sRef_killComplete (fref, loc);
2691 else if (alkind_isKeep (tkind))
2695 if (!sRef_isNSLocalVar (tref))
2697 sRef_setKeptComplete (fref, loc);
2701 else if (alkind_isShared (tkind))
2703 if (!ffix) { sRef_setShared (fref, loc); }
2705 else if (alkind_isLocal (tkind) || alkind_isUnknown (tkind))
2707 if (transferType == TT_DOASSIGN || transferType == TT_FCNRETURN)
2710 ** local shares fresh. Make it owned/dependent.
2715 sRef_setOwned (tref, loc);
2720 sRef_setDependentComplete (fref, loc);
2723 /* NO! sRef_clearAliasKind (fref); */
2727 if (context_getFlag (FLG_PASSUNKNOWN))
2729 sRef_clearAliasKind (fref);
2740 checkTransferExposure (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2741 sRef tref, exprNode texp, bool tfix,
2743 transferKind transferType)
2745 alkind fkind = sRef_getAliasKind (fref);
2746 alkind tkind = sRef_getAliasKind (tref);
2747 exkind tekind = sRef_getExKind (tref);
2749 if (sRef_isObserver (fref) && ctype_isMutable (sRef_getType (fref)))
2752 ** observer -> exposed or observer
2756 ** observer -> temp is okay [NO! really? only in function calls]
2759 if (sRef_isExposed (tref) || sRef_isObserver (tref)
2760 || alkind_isLocal (tkind))
2764 if ((transferType == TT_DOASSIGN) && alkind_isLocal (tkind))
2766 if (!tfix) { sRef_setAliasKindComplete (tref, fkind, loc); }
2771 if (transferType == TT_FCNRETURN
2772 || transferType == TT_DOASSIGN
2773 || transferType == TT_FIELDASSIGN
2774 || transferType == TT_GLOBINIT)
2776 bool hasError = FALSE;
2778 if (exprNode_isStringLiteral (fexp)
2779 && transferType == TT_GLOBINIT)
2781 hasError = optgenerror
2783 message ("Read-only string literal storage %q%q: %q",
2784 sRef_unparseOpt (fref),
2785 transferErrorExpMessage (transferType, tekind),
2786 generateText (fexp, texp, tref, transferType)),
2789 sRef_setAliasKind (fref, AK_ERROR, fileloc_undefined);
2793 if ((transferType == TT_DOASSIGN
2794 || transferType == TT_FIELDASSIGN)
2795 && (sRef_isNSLocalVar (tref)
2796 || (exprNode_isStringLiteral (fexp)
2797 && ctype_isRealArray (exprNode_getType (texp)))))
2799 ; /* No error for local assignment or assignment
2800 to static array (copies string). */
2804 if (exprNode_isStringLiteral (fexp))
2806 hasError = optgenerror
2809 ("Read-only string literal storage %q%q: %q",
2810 sRef_unparseOpt (fref),
2811 transferErrorExpMessage (transferType, tekind),
2812 generateText (fexp, texp, tref, transferType)),
2819 hasError = optgenerror
2822 ("Observer storage %q%q: %q",
2823 sRef_unparseOpt (fref),
2824 transferErrorExpMessage (transferType, tekind),
2825 generateText (fexp, texp, tref, transferType)),
2833 if (transferType != TT_GLOBINIT)
2835 sRef_showExpInfo (fref);
2836 sRef_setAliasKind (tref, AK_ERROR, loc);
2841 if (transferType == TT_DOASSIGN && !tfix)
2843 DPRINTF (("Setting unknown!"));
2844 /* sRef_setAliasKind (tref, AK_ERROR, loc); */
2848 else /* TT_FCNPASS */
2850 llassert (transferType == TT_FCNPASS);
2852 if (alkind_isTemp (tkind)
2853 || alkind_isDependent (tkind)
2854 || alkind_isRefCounted (tkind))
2860 if (!alkind_isError (tkind))
2864 message ("Observer storage %q%q: %q",
2865 sRef_unparseOpt (fref),
2866 transferErrorMessage (transferType, tkind),
2867 generateText (fexp, texp, tref, transferType)),
2870 sRef_showExpInfo (fref);
2871 sRef_clearAliasState (fref, loc);
2878 else if (sRef_isExposed (fref) && ctype_isMutable (sRef_getType (fref)))
2880 if (transferType == TT_FCNRETURN)
2882 if (!(sRef_isExposed (tref) || sRef_isObserver (tref)
2883 || sRef_isParam (fref)))
2887 message ("Exposed storage %q%q: %q",
2888 sRef_unparseOpt (fref),
2889 transferErrorExpMessage (transferType, tekind),
2890 generateText (fexp, texp, tref, transferType)),
2893 sRef_showExpInfo (fref);
2897 else if (transferType == TT_FCNPASS)
2899 if (!(sRef_isExposed (tref)
2900 || sRef_isObserver (tref)
2901 || (alkind_isUnknown (tkind)
2902 || alkind_isDependent (tkind)
2903 || alkind_isTemp (tkind)
2904 || alkind_isKillRef (tkind)
2905 || alkind_isRefCounted (tkind))))
2907 if (alkind_isUnique (tkind) || alkind_isError (tkind))
2914 message ("Exposed storage %q%q: %q",
2915 sRef_unparseOpt (fref),
2916 transferErrorMessage (transferType, tkind),
2917 generateText (fexp, texp, tref, transferType)),
2920 sRef_showExpInfo (fref);
2921 sRef_clearAliasState (fref, loc);
2931 else if (transferType == TT_DOASSIGN)
2933 if (!(sRef_isExposed (tref)
2934 || !sRef_isCvar (tref)
2935 || (alkind_isUnknown (tkind)
2936 || alkind_isDependent (tkind)
2937 || alkind_isRefCounted (tkind)
2938 || alkind_isNewRef (tkind)
2939 || alkind_isFresh (tkind)
2940 || alkind_isLocal (tkind))))
2944 message ("Exposed storage %q%q: %q",
2945 sRef_unparseOpt (fref),
2946 transferErrorExpMessage (transferType, tekind),
2947 generateText (fexp, texp, tref, transferType)),
2950 sRef_showExpInfo (fref);
2953 if (!tfix) { sRef_setExposed (tref, loc); }
2957 llassert (transferType == TT_GLOBPASS
2958 || transferType == TT_GLOBRETURN
2959 || transferType == TT_PARAMRETURN
2960 || transferType == TT_LEAVETRANS
2961 || transferType == TT_GLOBINIT);
2971 ** returns TRUE if there is no error reported
2973 ** if fixt, don't change tref (except if error reported.)
2974 ** if fixf, don't change fref (except if error reported.)
2978 checkTransferAux (exprNode fexp, sRef fref, bool ffix,
2979 exprNode texp, sRef tref, bool tfix,
2980 fileloc loc, transferKind transferType)
2984 bool isassign = (transferType == TT_DOASSIGN);
2985 bool isfieldassign = (transferType == TT_FIELDASSIGN);
2986 bool iseitherassign = isassign || (transferType == TT_FIELDASSIGN);
2987 bool isfcnpass = (transferType == TT_FCNPASS);
2988 bool isfcnreturn = (transferType == TT_FCNRETURN);
2992 /*start modification David Larochelle */
2997 checkTransferNullTerminatedAux (fref, fexp, ffix, tref, texp, tfix,
3000 /*end modification */
3005 checkTransferNullAux (fref, fexp, ffix, tref, texp, tfix,
3012 checkTransferAssignAux (fref, fexp, ffix, tref, texp, tfix,
3017 ** Check for definition
3021 ** errors passing out params already detected in checkAnyCall
3029 || (!sRef_isNSLocalVar (tref)
3030 && (sRef_isAnyDefined (tref) || !sRef_stateKnown (tref))))
3034 if (!ynm_toBoolRelaxed
3035 (checkCompletelyDefined (fexp, fref, texp, tref,
3037 loc, transferType, 0, TRUE)))
3045 if (defok && iseitherassign)
3047 sRef_setDefState (tref, sRef_getDefState (fref), loc);
3057 checkTransferExposure (fref, fexp, ffix, tref, texp, tfix,
3060 fkind = sRef_getAliasKind (fref);
3061 tkind = sRef_getAliasKind (tref);
3067 if (alkind_isOnly (fkind))
3070 checkOnlyTransferAux (fref, fexp, ffix,
3074 else if (alkind_isFresh (fkind))
3077 checkFreshTransferAux (fref, fexp, ffix,
3081 else if (alkind_isOwned (fkind))
3084 checkOwnedTransferAux (fref, fexp, ffix,
3088 else if (alkind_isDependent (fkind))
3092 (sRef_isExposed (tref) || sRef_isObserver (tref)))
3096 else if ((alkind_isOnly (tkind) || alkind_isKeep (tkind)
3097 || alkind_isOwned (tkind))
3098 || (!isfcnpass && alkind_isTemp (tkind)))
3102 if (sRef_isLocalVar (fref))
3104 sRef depRef = dependentReference (fref);
3106 if (sRef_isValid (depRef) && sRef_isLocalVar (depRef))
3109 sRef_kill (depRef, loc);
3110 sRef_kill (fref, loc);
3120 if (canLoseLocalReference (fref, loc))
3128 (FLG_DEPENDENTTRANS,
3129 message ("%s storage %q%q: %q",
3130 alkind_capName (fkind),
3131 sRef_unparseOpt (fref),
3132 transferErrorMessage (transferType, tkind),
3133 generateText (fexp, texp, tref, transferType)),
3136 DPRINTF (("Here: %s / %s",
3137 sRef_unparseFull (fref),
3138 sRef_unparseFull (tref)));
3140 sRef_showAliasInfo (fref);
3146 if (isassign && (alkind_isFresh (tkind) || alkind_isLocal (tkind)))
3150 sRef_setDependent (tref, loc);
3155 else if (alkind_isShared (fkind))
3162 if (alkind_isOnly (tkind)
3164 && (!(sRef_isObserver (tref) || sRef_isExposed (tref))
3165 && alkind_isTemp (tkind))))
3169 message ("%s storage %q%q: %q",
3170 alkind_capName (fkind),
3171 sRef_unparseOpt (fref),
3172 transferErrorMessage (transferType, tkind),
3173 generateText (fexp, texp, tref, transferType)),
3176 sRef_showAliasInfo (fref);
3181 if (alkind_isFresh (tkind) || alkind_isLocal (tkind))
3183 sRef_setShared (tref, loc);
3187 else if (alkind_isKeep (fkind))
3191 if (alkind_isKeep (tkind)
3192 || alkind_isLocal (tkind)
3193 || (isfcnreturn && sRef_isExposed (tref))
3195 && (alkind_isOnly (tkind) || alkind_isOwned (tkind))))
3197 sRef_setKept (fref, loc);
3200 && (alkind_isTemp (tkind) || alkind_isOwned (tkind)))
3206 if (!alkind_isError (tkind))
3210 message ("%s storage %q: %q",
3211 alkind_capName (fkind),
3212 transferErrorMessage (transferType, tkind),
3213 generateText (fexp, texp, tref, transferType)),
3216 sRef_showAliasInfo (fref);
3221 else if (alkind_isTemp (fkind) || alkind_isKept (fkind))
3227 if (alkind_isOnly (tkind)
3228 || alkind_isShared (tkind)
3229 || (alkind_isTemp (fkind)
3230 && !isfcnreturn && alkind_isDependent (tkind))
3231 || alkind_isOwned (tkind)
3232 || alkind_isKeep (tkind))
3234 if (!exprNode_isNullValue (fexp)
3235 && (ctype_isMutable (exprNode_getType (fexp))
3236 || (ctype_isArray (exprNode_getType (fexp))
3237 && sRef_isParam (fref)))
3238 && (!iseitherassign || sRef_isReference (tref)))
3240 if (sRef_isThroughArrayFetch (fref))
3243 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3244 FLG_STRICTUSERELEASED,
3245 message ("%s storage %q%q: %q",
3246 alkind_capName (fkind),
3247 sRef_unparseOpt (fref),
3248 transferErrorMessage (transferType, tkind),
3249 generateText (fexp, texp, tref, transferType)),
3252 sRef_showAliasInfo (fref);
3258 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3259 message ("%s storage %q%q: %q",
3260 alkind_capName (fkind),
3261 sRef_unparseOpt (fref),
3262 transferErrorMessage (transferType, tkind),
3263 generateText (fexp, texp, tref, transferType)),
3266 sRef_showAliasInfo (fref);
3272 else if (alkind_isRefCounted (fkind) || alkind_isKillRef (fkind))
3274 if (alkind_isNewRef (tkind))
3277 ** check that the refs field has been modified
3280 if (!sRef_isConst (fref))
3284 message ("Reference counted storage returned without modifying "
3285 "reference count: %s",
3286 exprNode_unparse (fexp)),
3290 else if (iseitherassign)
3292 if (alkind_isRefCounted (fkind))
3294 if (!sRef_isLocalVar (tref))
3299 ("Assignment to non-local from reference counted storage: %s",
3300 exprNode_unparse (fexp)),
3302 ("Reference counted storage should call a function returning "
3303 "a newref instead of direct assignments."),
3314 if (alkind_isRefCounted (tkind) || alkind_isTemp (tkind))
3316 /* okay --- no change in state */
3318 else if (alkind_isKillRef (tkind))
3320 if (!ffix && !tfix && !(transferType == TT_FCNRETURN))
3322 sRef_killComplete (fref, loc);
3327 if (!alkind_isError (tkind))
3331 message ("Reference counted storage %q: %q",
3332 transferErrorMessage (transferType, tkind),
3333 generateText (fexp, texp, tref, transferType)),
3346 if (alkind_isOnly (tkind) || alkind_isKeep (tkind))
3348 if (sRef_isAddress (fref))
3351 (FLG_IMMEDIATETRANS,
3352 message ("Immediate address %q %q: %q",
3353 sRef_unparse (fref),
3354 transferErrorMessage (transferType, tkind),
3355 generateText (fexp, texp, tref, transferType)),
3358 sRef_setAliasKind (fref, AK_ERROR, loc);
3362 if ((alkind_isUnknown (fkind) || alkind_isStatic (fkind))
3363 && !sRef_isDefinitelyNull (fref)
3365 && (!exprNode_isNullValue (fexp)))
3367 flagcode errkind = alkind_isStatic (fkind)
3368 ? FLG_STATICTRANS : FLG_UNKNOWNTRANS;
3370 if (transferType == TT_GLOBINIT)
3372 if (errkind == FLG_STATICTRANS)
3374 errkind = FLG_STATICINITTRANS;
3378 errkind = FLG_UNKNOWNINITTRANS;
3384 message ("%s storage %s %q: %q",
3385 alkind_capName (fkind),
3386 exprNode_unparse (fexp),
3387 transferErrorMessage (transferType, tkind),
3388 generateText (fexp, texp, tref, transferType)),
3391 sRef_showAliasInfo (fref);
3396 /* don't kill shared to suppress future messages */
3397 if (!alkind_isShared (fkind))
3403 /*< yuk! should do this in aliasaux >*/
3405 if (!sRef_isNSLocalVar (tref) && !sRef_sameName (fref, tref))
3409 sRef_setKeptComplete (fref, loc);
3413 sRef_setKept (fref, loc);
3424 if (alkind_isKeep (tkind))
3426 sRef_setKeptComplete (fref, loc);
3430 sRef_killComplete (fref, loc);
3435 if (alkind_isKeep (tkind))
3437 sRef_setKept (fref, loc);
3441 sRef_kill (fref, loc);
3448 else if (alkind_isOwned (tkind))
3450 /* don't kill shared to suppress future messages */
3451 if (!alkind_isShared (fkind))
3454 || !sRef_sameName (fref, tref)) /* result of return parameter */
3460 sRef_setDependentComplete (fref, loc);
3464 sRef_setDependent (fref, loc);
3470 else if (alkind_isShared (tkind))
3472 if (alkind_isFresh (fkind) || alkind_isLocal (fkind))
3476 sRef_setShared (fref, loc);
3480 else if (alkind_isUnknown (tkind) && context_getFlag (FLG_MEMIMPLICIT))
3482 if (alkind_isDependent (fkind))
3484 if (!exprNode_isNullValue (fexp)
3485 && ctype_isMutable (exprNode_getType (fexp))
3486 && (!iseitherassign || sRef_isReference (tref)))
3488 if (canLoseReference (fref, loc))
3495 (FLG_DEPENDENTTRANS,
3496 message ("%s storage %q%q: %q",
3497 alkind_capName (fkind),
3498 sRef_unparseOpt (fref),
3499 transferErrorMessage (transferType, tkind),
3500 generateText (fexp, texp, tref, transferType)),
3503 DPRINTF (("Here: %s / %s", sRef_unparseFull (fref),
3504 sRef_unparseFull (tref)));
3505 sRef_showAliasInfo (fref);
3511 else if (alkind_isNewRef (tkind))
3515 sRef_killComplete (fref, loc);
3518 else if (alkind_isKillRef (tkind))
3520 if (transferType == TT_FCNRETURN)
3522 if (sRef_isNewRef (fref))
3526 message ("New reference returned as temp reference: %q",
3527 generateText (fexp, texp, tref, transferType)),
3530 sRef_showAliasInfo (fref);
3536 if (sRef_isNewRef (fref))
3538 sRef_killComplete (fref, loc);
3542 if (sRef_isRefCounted (fref)
3543 && sRef_isCvar (fref)
3544 && !sRef_isLocalVar (fref))
3549 ("External reference counted storage released: %q",
3550 generateText (fexp, texp, tref, transferType)),
3553 sRef_showAliasInfo (fref);
3569 ** assigns fexp := tref or passes fexp as a parameter, or returns fexp.
3571 ** For assignments, sets alias and definition state accordingly.
3575 checkTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref,
3576 fileloc loc, transferKind transferType)
3580 if (context_inProtectVars ())
3586 ** for local references, we need to check
3587 ** the transfer for all possible aliases.
3590 if (sRef_isLocalVar (tref) && transferType != TT_DOASSIGN)
3592 sRefSet alias = usymtab_allAliases (tref);
3594 sRefSet_realElements (alias, atref)
3596 sRef abase = sRef_getRootBase (atref);
3598 if (sRef_isKnown (atref)
3599 && !sRef_isLocalVar (abase)
3600 && !sRef_isExternal (abase))
3602 atref = sRef_updateSref (atref);
3604 if (sRef_hasName (atref))
3606 if (!sRef_isNew (atref)
3607 && !sRef_sameName (tref, atref))
3609 context_setAliasAnnote (atref, tref);
3612 checkTransferAux (fexp, fref, TRUE,
3616 context_clearAliasAnnote ();
3619 } end_sRefSet_realElements;
3621 sRefSet_free (alias);
3625 if (sRef_isLocalVar (fref))
3627 sRefSet alias = usymtab_allAliases (fref);
3629 sRefSet_realElements (alias, afref)
3631 sRef abase = sRef_getRootBase (afref);
3633 if (sRef_isKnown (afref)
3634 && !sRef_isLocalVar (abase)
3635 && !sRef_isExternal (abase))
3637 afref = sRef_updateSref (afref);
3639 if (sRef_hasName (afref))
3641 if (!sRef_isNew (afref)
3642 && !sRef_sameName (afref, fref))
3644 context_setAliasAnnote (afref, fref);
3647 checkTransferAux (fexp, afref, FALSE,
3651 context_clearAliasAnnote ();
3654 } end_sRefSet_realElements;
3656 sRefSet_free (alias);
3661 checkTransferAux (fexp, fref, FALSE, texp, tref, FALSE,
3667 static /*@exposed@*/ sRef
3668 dependentReference (sRef sr)
3670 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
3673 ** If there is a local variable that aliases sr, then there is no
3674 ** error. Make the local an only.
3677 if (!sRefSet_isEmpty (ab))
3679 sRef res = sRef_undefined;
3682 ** make one an only, others alias it
3686 sRefSet_realElements (ab, current)
3688 if (sRef_isOwned (current))
3693 } end_sRefSet_realElements;
3699 return sRef_undefined;
3702 bool canLoseReference (sRef sr, fileloc loc)
3704 bool gotone = FALSE;
3705 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
3709 ** if there is a local variable that aliases sr, then there is no
3710 ** error. Make the local an only.
3713 if (!sRefSet_isEmpty (ab))
3716 ** make one an only, others alias it
3720 sRefSet_realElements (ab, current)
3722 sRef_setLastReference (current, sr, loc);
3725 } end_sRefSet_realElements;
3733 bool canLoseLocalReference (sRef sr, fileloc loc)
3735 bool gotone = FALSE;
3736 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
3740 ** if there is a local variable that aliases sr, then there is no
3741 ** error. Make the local an only.
3744 if (!sRefSet_isEmpty (ab))
3747 ** make one an only, others alias it
3751 sRefSet_realElements (ab, current)
3753 if (sRef_isRealLocalVar (sRef_getRootBase (current)))
3755 sRef_setLastReference (current, sr, loc);
3759 } end_sRefSet_realElements;
3768 /*start modification */
3770 /*added by David Larochelle 4/13/2000*/
3772 /*this is modeled after checkTransferNullAux */
3775 checkTransferNullTerminatedAux (sRef fref, exprNode fexp,
3776 /*@unused@*/ bool ffix,
3777 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
3778 fileloc loc, transferKind transferType)
3780 alkind tkind = sRef_getAliasKind (tref);
3781 ctype ttyp = ctype_realType (sRef_getType (tref));
3784 printf ("checking for fexp-%s\n", exprNode_unparse(fexp));
3785 printf ("checking for texp-%s\n", exprNode_unparse(texp));
3788 if (ctype_isUnknown (ttyp))
3790 ttyp = exprNode_getType (texp);
3792 if (ctype_isUnknown (ttyp))
3794 ttyp = exprNode_getType (fexp);
3796 if (ctype_isUnknown (ttyp))
3798 ttyp = sRef_getType (fref);
3803 if (ctype_isFunction (ttyp) && (transferType == TT_FCNRETURN))
3805 ttyp = ctype_returnValue (ttyp);
3809 ** check for null terminated (don't need to check aliases??)
3812 if (!sRef_isNullTerminated (fref)
3813 && !usymtab_isGuarded (fref)
3814 && ctype_isRealAP (ttyp))
3816 if (!alkind_isLocal (tkind) && !alkind_isFresh (tkind)
3817 //this should be perhapsNullTerminated but I didn't want to write
3818 && (sRef_isPossiblyNullTerminated (tref) ||
3819 sRef_isNullTerminated (tref))
3820 && !(transferType == TT_DOASSIGN))
3822 if (transferType == TT_GLOBINIT)
3824 printf("-----------------------------------NULLTERMINATED ERROR1\n");
3825 if (sRef_isPossiblyNullTerminated (fref)) {
3827 (FLG_NULLTERMINATEDWARNING,
3828 message ("%s %q initialized to %s value: %q",
3829 sRef_getScopeName (tref),
3830 sRef_unparse (tref),
3831 sRef_ntMessage (fref),
3832 generateText (fexp, texp, tref, transferType)),
3836 printf ("NULLTERMINATED REFERENCE ERROR\n");
3837 // printf ("First way\n");
3843 (FLG_NULLTERMINATED,
3844 message ("%s %q initialized to %s value: %q",
3845 sRef_getScopeName (tref),
3846 sRef_unparse (tref),
3847 sRef_ntMessage (fref),
3848 generateText (fexp, texp, tref, transferType)),
3852 printf ("NULLTERMINATED REFERENCE ERROR\n");
3853 // printf ("First way\n");
3856 printf("-----------------------------\n\n");
3862 printf("****************************NULLTERMINATED ERROR2\n");
3863 // ((transferType == TT_FCNPASS) ? FLG_NULLPASS : FLG_NULLRET,
3865 if (sRef_isPossiblyNullTerminated (fref))
3869 (FLG_NULLTERMINATEDWARNING,
3870 message ("%q storage %q%s: %q",
3871 /*@i777@*/cstring_capitalize (sRef_ntMessage (fref)),
3872 sRef_unparseOpt (fref),
3873 transferNTMessage (transferType),
3874 generateText (fexp, texp, tref, transferType)),
3878 printf ("NULLTERMINATED REFERENCE ERROR\n");
3879 // printf ("First way\n");
3884 ((transferType == TT_FCNPASS) ? FLG_NULLTERMINATED: FLG_NULLTERMINATED,
3885 message ("%q storage %q%s: %q",
3886 /*@i77@*/cstring_capitalize (sRef_ntMessage (fref)),
3887 sRef_unparseOpt (fref),
3888 transferNTMessage (transferType),
3889 generateText (fexp, texp, tref, transferType)),
3892 // sRef_showNullInfo (fref);
3893 // sRef_setNullError (fref);
3894 printf ("SYMBOL REFERENCED IS NOT NULLTERMINATED!\n");
3897 printf("*******************************=\n\n");
3907 /* end modification */