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) ;
51 ** returns the most specific alkind
54 alkind alkind_resolve (alkind a1, alkind a2)
56 if (a1 == AK_UNKNOWN || a1 == AK_ERROR) return a2;
57 if (a2 == AK_UNKNOWN || a2 == AK_ERROR || a2 == AK_LOCAL) return a1;
58 if (a1 == AK_LOCAL) return a2;
66 ** FCNRETURN return fref; tref is return type
67 ** GLOBASSIGN tref = fref;
68 ** FCNPASS call (fref) ; tref is the argument type
72 static /*@only@*/ cstring
73 transferErrorMessage (transferKind transferType, alkind tkind) /*@*/
78 return (message ("returned as %s", alkind_unparse (tkind)));
80 return (message ("assigned to %s", alkind_unparse (tkind)));
82 return (message ("assigned to %s", alkind_unparse (tkind)));
84 return (message ("used as initial value for %s",
85 alkind_unparse (tkind)));
87 return (message ("passed as %s param", alkind_unparse (tkind)));
94 transferErrorExpMessage (transferKind transferType, exkind tkind) /*@*/
96 if (exkind_isUnknown (tkind))
101 return (cstring_makeLiteral ("returned without qualification"));
104 return (cstring_makeLiteral ("assigned to unqualified reference"));
106 return (cstring_makeLiteral ("passed without qualification"));
108 return (cstring_makeLiteral ("used as initial value for unqualified storage"));
114 switch (transferType)
117 return (message ("returned as %s", exkind_unparse (tkind)));
120 return (message ("assigned to %s", exkind_unparse (tkind)));
122 return (message ("passed as %s param", exkind_unparse (tkind)));
130 static /*@observer@*/ cstring
131 transferNullMessage (transferKind transferType) /*@*/
133 switch (transferType)
136 return (cstring_makeLiteralTemp ("returned as non-null"));
139 return (cstring_makeLiteralTemp ("assigned to non-null"));
141 return (cstring_makeLiteralTemp ("initialized to non-null"));
143 return (cstring_makeLiteralTemp ("passed as non-null param"));
149 static /*@observer@*/ cstring
150 transferNTMessage (transferKind transferType) /*@*/
152 switch (transferType)
155 return (cstring_makeLiteralTemp ("returned as nullterminated"));
158 return (cstring_makeLiteralTemp ("assigned to nullterminated"));
160 return (cstring_makeLiteralTemp ("initialized to nullterminated"));
162 return (cstring_makeLiteralTemp ("passed as nullterminated param"));
168 static /*@dependent@*/ exprNode atFunction = exprNode_undefined;
169 static int atArgNo = 0;
170 static int atNumArgs = 0;
172 static cstring generateText (exprNode e1, exprNode e2,
173 sRef tref, transferKind tt)
176 if (tt == TT_DOASSIGN || tt == TT_GLOBINIT)
178 return (message ("%s = %s", exprNode_unparse (e2),
179 exprNode_unparse (e1)));
181 else if (tt == TT_FIELDASSIGN)
183 return (message ("%s = %s (field %q)",
184 exprNode_unparse (e2),
185 exprNode_unparse (e1),
186 sRef_unparse (tref)));
188 else if (tt == TT_FCNPASS)
190 return (message ("%s (%s%s%s)",
191 exprNode_unparse (atFunction),
192 (atArgNo == 1 ? cstring_undefined
193 : cstring_makeLiteralTemp ("..., ")),
194 exprNode_unparse (e1),
195 (atArgNo == atNumArgs ? cstring_undefined
196 : cstring_makeLiteralTemp (", ..."))));
200 return (cstring_copy (exprNode_unparse (e1)));
204 static /*@observer@*/ cstring
205 transferType_unparse (transferKind transferType) /*@*/
207 switch (transferType)
210 return (cstring_makeLiteralTemp ("Returned"));
213 return (cstring_makeLiteralTemp ("Assigned"));
215 return (cstring_makeLiteralTemp ("Passed"));
217 return (cstring_makeLiteralTemp ("Initialized"));
219 return (cstring_makeLiteralTemp ("GLOB RETURN!"));
221 return (cstring_makeLiteralTemp ("GLOB PASS!"));
223 return (cstring_makeLiteralTemp ("PARAM RETURN!"));
225 return (cstring_makeLiteralTemp ("LEAVE TRANS!"));
231 static /*@observer@*/ cstring udError (sRef s)
235 return cstring_makeLiteralTemp ("released");
237 else if (sRef_isAllocated (s))
239 return cstring_makeLiteralTemp ("allocated but not defined");
243 return cstring_makeLiteralTemp ("undefined");
248 cstring defExpl (sRef s) /*@*/
250 sRef rb = sRef_getRootBase (s);
252 if (sRef_sameName (rb, s))
254 if (sRef_isAllocated (s))
256 return cstring_makeLiteral (" (allocated only)");
258 return cstring_undefined;
262 return (message (" (%q is %s)", sRef_unparse (s), udError (s)));
267 ** returns TRUE if fref is completely defined.
268 ** if !report, returns TRUE unless error is at the deep level.
272 checkCompletelyDefined (exprNode fexp, sRef fref,
273 exprNode texp, sRef tref,
274 bool topLevel, bool inUnion, bool directUnion,
275 fileloc loc, transferKind transferType,
276 int depth, bool report)
279 alkind fkind = sRef_getAliasKind (fref);
280 alkind tkind = sRef_getAliasKind (tref);
282 if (depth > MAXDEPTH)
286 ("Check definition limit exceeded, checking %q. "
287 "This either means there is a variable with at least "
288 "%d indirections apparent in the program text, or "
289 "there is a bug in LCLint.",
296 if (!sRef_isKnown (fref))
301 if (alkind_isStack (fkind))
303 ctype rt = ctype_realType (sRef_getType (tref));
305 if (ctype_isMutable (rt) && !ctype_isSU (rt))
307 if (transferType == TT_PARAMRETURN)
312 ("Stack-allocated storage %qreachable from parameter %q",
313 sRef_unparseOpt (fref),
314 sRef_unparse (sRef_getRootBase (fref))),
317 sRef_showAliasInfo (fref);
320 else if (transferType == TT_GLOBRETURN)
325 ("Stack-allocated storage %qreachable from global %q",
326 sRef_unparseOpt (fref),
327 sRef_unparse (sRef_getRootBase (fref))),
330 sRef_showAliasInfo (fref);
333 else if (transferType == TT_FCNRETURN)
338 ("Stack-allocated storage %qreachable from return value: %s",
339 sRef_unparseOpt (fref),
340 exprNode_unparse (fexp)),
343 sRef_showAliasInfo (fref);
355 if ((sRef_isObserver (fref) && !sRef_isObserver (tref))
356 || (sRef_isExposed (fref) && !(sRef_isObserver (tref)
357 || sRef_isExposed (tref))))
359 flagcode code = (sRef_isObserver (fref)
360 ? FLG_OBSERVERTRANS : FLG_EXPOSETRANS);
362 if (!sRef_isStateLive (fref))
364 ; /* no error (will be a definition error) */
366 else if (transferType == TT_DOASSIGN
367 || transferType == TT_FIELDASSIGN
368 || transferType == TT_GLOBINIT
369 || transferType == TT_FCNPASS)
373 else if (transferType == TT_PARAMRETURN)
378 ("%s storage %qreachable from %s parameter",
379 exkind_capName (sRef_getExKind (fref)),
380 sRef_unparseOpt (fref),
381 exkind_unparseError (sRef_getExKind (tref))),
384 sRef_showExpInfo (fref);
385 sRef_setExKind (fref, XO_UNKNOWN, loc);
388 else if (transferType == TT_LEAVETRANS)
392 else if (transferType == TT_GLOBINIT)
397 ("%s storage %qreachable from %s initial value",
398 exkind_capName (sRef_getExKind (fref)),
399 sRef_unparseOpt (fref),
400 exkind_unparseError (sRef_getExKind (tref))),
403 sRef_showExpInfo (fref);
404 sRef_setExKind (fref, XO_UNKNOWN, loc);
407 else if (transferType == TT_GLOBRETURN)
412 ("%s storage %qreachable from %s global",
413 exkind_capName (sRef_getExKind (fref)),
414 sRef_unparseOpt (fref),
415 exkind_unparseError (sRef_getExKind (tref))),
418 sRef_showExpInfo (fref);
419 sRef_setExKind (fref, XO_UNKNOWN, loc);
422 else if (transferType == TT_FCNRETURN)
427 ("%s storage %qreachable from %s return value",
428 exkind_capName (sRef_getExKind (fref)),
429 sRef_unparseOpt (fref),
430 exkind_unparseError (sRef_getExKind (tref))),
433 sRef_showExpInfo (fref);
434 sRef_setExKind (fref, XO_UNKNOWN, loc);
439 llcontbug (message ("Transfer type: %s",
440 transferType_unparse (transferType)));
445 ("%s storage %qreachable from %s return value",
446 exkind_capName (sRef_getExKind (fref)),
447 sRef_unparseOpt (fref),
448 exkind_unparseError (sRef_getExKind (tref))),
451 sRef_showExpInfo (fref);
452 sRef_setExKind (fref, XO_UNKNOWN, loc);
458 if (!alkind_compatible (fkind, tkind))
460 if (fkind == AK_UNKNOWN && !sRef_isStateLive (fref))
462 ; /* no error (will be a definition error) */
464 else if (transferType == TT_DOASSIGN)
468 else if (transferType == TT_FCNPASS)
470 if (alkind_isKnown (sRef_getAliasKind (tref)))
475 ("Storage %qreachable from passed parameter "
476 "is %s (should be %s): %s",
477 sRef_unparseOpt (fref),
478 alkind_unparse (sRef_getAliasKind (fref)),
479 alkind_unparse (sRef_getAliasKind (tref)),
480 exprNode_unparse (fexp)),
483 sRef_showAliasInfo (fref);
487 else if (transferType == TT_PARAMRETURN)
489 bool noerror = FALSE;
491 if (alkind_isDependent (sRef_getAliasKind (fref)))
493 if (canLoseLocalReference (fref, loc))
503 ("Storage %qreachable from parameter is %s (should be %s)",
504 sRef_unparseOpt (fref),
505 alkind_unparse (sRef_getAliasKind (fref)),
506 alkind_unparse (sRef_getAliasKind (tref))),
509 sRef_showAliasInfo (fref);
512 else if (transferType == TT_LEAVETRANS)
517 ("Storage %qreachable from temporary reference is %s "
518 "at scope exit (should be %s)",
519 sRef_unparseOpt (fref),
520 alkind_unparse (sRef_getAliasKind (fref)),
521 alkind_unparse (sRef_getAliasKind (tref))),
524 sRef_showAliasInfo (fref);
527 else if (transferType == TT_GLOBRETURN)
532 ("Storage %qreachable from global is %s (should be %s)",
533 sRef_unparseOpt (fref),
534 alkind_unparse (sRef_getAliasKind (fref)),
535 alkind_unparse (sRef_getAliasKind (tref))),
538 sRef_showAliasInfo (fref);
541 else if (transferType == TT_FCNRETURN)
546 ("Storage %qreachable from return value is %s (should be %s)",
547 sRef_unparseOpt (fref),
548 alkind_unparse (sRef_getAliasKind (fref)),
549 alkind_unparse (sRef_getAliasKind (tref))),
552 sRef_showAliasInfo (fref);
555 else if (transferType == TT_GLOBINIT)
560 ("Storage %qreachable from initial value is %s (should be %s)",
561 sRef_unparseOpt (fref),
562 alkind_unparse (sRef_getAliasKind (fref)),
563 alkind_unparse (sRef_getAliasKind (tref))),
566 sRef_showAliasInfo (fref);
571 llcontbug (message ("Transfer type: %s",
572 transferType_unparse (transferType)));
577 ("Storage %qreachable from return value is %s (should be %s)",
578 sRef_unparseOpt (fref),
579 alkind_unparse (sRef_getAliasKind (fref)),
580 alkind_unparse (sRef_getAliasKind (tref))),
583 sRef_showAliasInfo (fref);
588 if (sRef_isDead (fref))
595 if (transferType == TT_PARAMRETURN)
600 ("Released storage %q reachable from parameter at return point",
601 sRef_unparse (fref)),
604 sRef_showStateInfo (fref);
608 else if (transferType == TT_LEAVETRANS)
612 message ("Released storage %q reachable from temporary "
613 "reference at scope exit",
614 sRef_unparse (fref)),
617 sRef_showStateInfo (fref);
621 else if (transferType == TT_GLOBRETURN)
625 message ("Released storage %q reachable from global",
626 sRef_unparse (fref)),
629 sRef_showStateInfo (fref);
633 else if (transferType == TT_FCNPASS)
637 message ("Released storage %q reachable from passed parameter",
638 sRef_unparse (fref)),
641 sRef_showStateInfo (fref);
649 message ("Released storage %q reachable from parameter",
650 sRef_unparse (fref)),
653 sRef_showStateInfo (fref);
661 && sRef_possiblyNull (fref)
662 && !sRef_perhapsNull (tref)
663 && ctype_isRealPointer (sRef_getType (tref))
664 && !usymtab_isGuarded (fref))
666 if (transferType == TT_FCNRETURN)
670 message ("%q storage %qderivable from return value: %s",
671 cstring_capitalize (sRef_nullMessage (fref)),
672 sRef_unparseOpt (fref),
673 exprNode_unparse (fexp)),
676 sRef_showNullInfo (fref);
677 sRef_setNullError (fref);
680 else if (transferType == TT_GLOBRETURN || transferType == TT_PARAMRETURN)
685 ("Function returns with %s storage derivable from %q %q",
686 sRef_nullMessage (fref),
687 cstring_makeLiteral ((transferType == TT_GLOBRETURN)
688 ? "global" : "parameter"),
689 sRef_unparse (fref)),
692 sRef_showNullInfo (fref);
693 sRef_setNullError (fref);
696 else if (transferType == TT_GLOBPASS)
700 message ("Function called with %s storage "
701 "derivable from global %q",
702 sRef_nullMessage (fref),
703 sRef_unparse (fref)),
706 sRef_showNullInfo (fref);
707 sRef_setNullError (fref);
710 else if (transferType == TT_FCNPASS)
714 message ("%q storage %qderivable from parameter %q",
715 cstring_capitalize (sRef_nullMessage (fref)),
716 sRef_unparseOpt (fref),
717 generateText (fexp, exprNode_undefined,
718 sRef_undefined, TT_FCNPASS)),
721 sRef_showNullInfo (fref);
722 sRef_setNullError (fref);
727 llassert (transferType == TT_DOASSIGN
728 || transferType == TT_GLOBINIT
729 || transferType == TT_LEAVETRANS);
733 if (sRef_isRelDef (tref)
734 || sRef_isPartial (tref)
735 || sRef_isAllocated (tref)
736 || sRef_isStateSpecial (tref))
738 /* should check fref is allocated? */
742 ct = ctype_realType (sRef_getType (fref));
744 if (!(sRef_isAnyDefined (fref)
745 || sRef_isPdefined (fref)
746 || sRef_isAllocated (fref)
747 || sRef_isStateUnknown (fref)))
749 if (transferType == TT_GLOBRETURN)
754 message ("Function returns with global %q not "
755 "completely defined%q",
756 sRef_unparse (sRef_getRootBase (fref)),
760 sRef_showStateInfo (fref);
761 sRef_setDefined (fref, loc);
764 else if (transferType == TT_GLOBPASS)
770 ("Function called with global %q not completely defined%q",
771 sRef_unparse (sRef_getRootBase (fref)),
775 sRef_showStateInfo (fref);
776 sRef_setDefined (fref, loc);
779 else if (transferType == TT_PARAMRETURN)
781 if (report && !topLevel
784 message ("Function returns storage %q reachable from parameter not "
785 "completely defined%q",
786 sRef_unparse (sRef_getRootBase (fref)),
790 sRef_showStateInfo (fref);
791 sRef_setDefined (fref, loc);
794 else if (transferType == TT_LEAVETRANS)
796 if (report && !topLevel
799 message ("Scope exits with storage %q reachable from "
800 "temporary reference not completely defined%q",
801 sRef_unparse (sRef_getRootBase (fref)),
805 sRef_showStateInfo (fref);
806 sRef_setDefined (fref, loc);
811 if (transferType != TT_DOASSIGN
812 && (!(sRef_isNew (fref) || sRef_isType (fref))))
816 if (sRef_isDead (fref))
820 message ("%s storage %qwas released: %q",
821 transferType_unparse (transferType),
822 sRef_unparseOpt (fref),
823 generateText (fexp, texp, tref, transferType)),
826 sRef_showStateInfo (fref);
834 ("%s storage %qnot completely defined%q: %q",
835 transferType_unparse (transferType),
836 sRef_unparseOpt (sRef_getRootBase (fref)),
838 generateText (fexp, texp, tref, transferType)),
841 sRef rb = sRef_getRootBase (fref);
842 sRef_showStateInfo (fref);
843 sRef_setDefinedComplete (rb, loc);
851 if (sRef_isAllocated (fref) && sRef_isValid (tref)
852 && (transferType == TT_DOASSIGN))
854 sRef_setAllocatedComplete (tref, loc);
863 if (ctype_isUnknown (ct))
867 else if (ctype_isPointer (ct))
869 ctype tct = ctype_realType (sRef_getType (tref));
871 if (sRef_isStateUnknown (fref))
877 if (ctype_isAP (tct) || ctype_isUnknown (tct))
879 sRef fptr = sRef_constructDeref (fref);
880 sRef tptr = sRef_constructDeref (tref);
882 return (checkCompletelyDefined (fexp, fptr, texp, tptr,
883 FALSE, inUnion, FALSE, loc,
884 transferType, depth + 1, report));
892 else if (ctype_isArray (ct))
896 else if (ctype_isStruct (ct))
898 ctype tct = ctype_realType (sRef_getType (tref));
900 if (ctype_match (ct, tct))
903 bool hasOneDefined = FALSE;
904 cstringSList badFields = cstringSList_undefined;
906 if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref))
911 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
913 sRefSet_realElements (sRef_derivedFields (fref), sr)
917 hasOneDefined = TRUE;
919 if (sRef_isField (sr))
921 cstring fieldname = sRef_getField (sr);
922 sRef fldref = sRef_makeField (tref, fieldname);
923 bool shouldCheck = !sRef_isRecursiveField (fldref);
929 (checkCompletelyDefined (fexp, sr, texp, fldref,
930 FALSE, inUnion, FALSE, loc,
931 transferType, depth + 1,
942 badFields = cstringSList_add (badFields,
946 } end_sRefSet_realElements;
948 else if (sRef_isAllocated (fref))
951 ** for structures, each field must be completely defined
954 uentryList fields = ctype_getFields (ct);
956 uentryList_elements (fields, ue)
959 cstring name = uentry_getRealName (ue);
960 sRef ffield = sRef_makeField (fref, name);
961 sRef tfield = sRef_makeField (tref, name);
962 bool shouldCheck = !sRef_isRecursiveField (tfield);
970 thisField = ynm_toBoolRelaxed
971 (checkCompletelyDefined (fexp, ffield, texp, tfield,
972 FALSE, inUnion, FALSE,
980 badFields = cstringSList_add (badFields, uentry_rawName (ue));
984 hasOneDefined = TRUE;
986 } end_uentryList_elements;
993 if (!isOk && (!inUnion || hasOneDefined))
995 if (transferType == TT_GLOBRETURN)
999 message ("Global storage %q contains %d undefined field%p "
1000 "when call returns: %q",
1001 sRef_unparse (fref),
1002 cstringSList_size (badFields),
1003 cstringSList_unparseAbbrev (badFields)),
1006 sRef_setDefined (fref, loc);
1009 else if (transferType == TT_GLOBPASS)
1013 message ("Global storage %q contains %d undefined field%p "
1015 sRef_unparse (fref),
1016 cstringSList_size (badFields),
1017 cstringSList_unparseAbbrev (badFields)),
1020 sRef_setDefined (fref, loc);
1023 else if (transferType == TT_PARAMRETURN)
1027 message ("Storage %qreachable from parameter "
1028 "contains %d undefined field%p: %q",
1029 sRef_unparseOpt (fref),
1030 cstringSList_size (badFields),
1031 cstringSList_unparseAbbrev (badFields)),
1034 sRef_setDefined (fref, loc);
1037 else if (transferType == TT_LEAVETRANS)
1045 message ("%s storage %qcontains %d undefined field%p: %q",
1046 transferType_unparse (transferType),
1047 sRef_unparseOpt (fref),
1048 cstringSList_size (badFields),
1049 cstringSList_unparseAbbrev (badFields)),
1052 sRef_setDefined (fref, loc);
1057 cstringSList_free (badFields);
1063 return (ynm_fromBool (hasOneDefined));
1072 return (ynm_fromBool (!report || isOk));
1080 else if (ctype_isUnion (ct))
1082 if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref))
1088 ctype tct = ctype_realType (sRef_getType (tref));
1090 if (ctype_isKnown (tct) && ctype_match (ct, tct))
1092 cstringSList goodFields = cstringSList_new ();
1094 int nelements = sRefSet_size (sRef_derivedFields (fref));
1097 ** for unions, at least one field must be completely defined
1100 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
1105 sRefSet_realElements (sRef_derivedFields (fref), sr)
1109 if (sRef_isField (sr))
1111 sRef fldref = sRef_makeField (tref, sRef_getField (sr));
1113 thisField = ynm_toBoolStrict
1114 (checkCompletelyDefined
1115 (fexp, sr, texp, fldref, FALSE, inUnion,
1116 (nelements > 1 ? TRUE : FALSE),
1117 loc, transferType, depth + 1, FALSE));
1121 goodFields = cstringSList_add
1122 (goodFields, sRef_getField (sr));
1125 } end_sRefSet_realElements;
1127 if (cstringSList_empty (goodFields)
1129 && context_getFlag (FLG_UNIONDEF))
1133 if (transferType == TT_PARAMRETURN)
1137 message ("Union %q reachable from parameter has "
1139 sRef_unparse (fref)),
1142 else if (transferType == TT_LEAVETRANS)
1146 message ("Union %q has no defined field at scope exit",
1147 sRef_unparse (fref)),
1150 else if (transferType == TT_DOASSIGN
1151 || transferType == TT_FIELDASSIGN
1152 || transferType == TT_GLOBINIT)
1160 message ("%s union %q has no defined field",
1161 transferType_unparse (transferType),
1162 sRef_unparse (fref)),
1169 cstringSList_free (goodFields);
1170 return ynm_fromBool (!report || isOk);
1183 ** fref is being free'd
1187 DSC_GLOB, DSC_LOCAL, DSC_PARAM, DSC_STRUCT
1190 static /*@observer@*/ cstring dscCode_unparse (dscCode desc) /*@*/
1195 return cstring_makeLiteralTemp ("killed global");
1197 return cstring_makeLiteralTemp ("variable declared in this scope");
1199 return cstring_makeLiteralTemp ("released storage");
1201 return cstring_makeLiteralTemp ("released structure parameter");
1208 checkCompletelyDestroyed (exprNode p_fexp, sRef p_fref, bool p_topLevel,
1209 fileloc p_loc, int p_depth, dscCode p_desc);
1211 bool checkGlobalDestroyed (sRef fref, fileloc loc)
1213 return (checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1217 void checkLocalDestroyed (sRef fref, fileloc loc)
1219 if (sRef_isObserver (fref) || sRef_isExposed (fref)
1220 || sRef_isPartial (fref))
1226 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1231 void checkStructDestroyed (sRef fref, fileloc loc)
1233 if (sRef_isObserver (fref) || sRef_isExposed (fref)
1234 || sRef_isPartial (fref))
1240 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE, loc, 0, DSC_STRUCT);
1245 checkCompletelyDestroyed (exprNode fexp, sRef fref, bool topLevel,
1246 fileloc loc, int depth,
1251 if (depth > MAXDEPTH)
1253 llquietbug (message ("checkCompletelyDestroyed: too deep: %s / %q",
1254 exprNode_unparse (fexp),
1255 sRef_unparseFull (fref)));
1259 if (!sRef_isKnown (fref)) return TRUE;
1260 if (usymtab_isProbableNull (fref)) return TRUE;
1261 if (!context_getFlag (FLG_COMPDESTROY)) return TRUE;
1262 if (!context_getFlag (FLG_MUSTFREE)) return TRUE;
1264 ct = ctype_realType (sRef_getType (fref));
1270 if (sRef_isFresh (fref) || sRef_isOnly (fref))
1274 if (sRef_isDead (fref)
1275 || sRef_isUnuseable (fref)
1276 || sRef_definitelyNull (fref)
1277 || sRef_isObserver (fref)
1278 || sRef_isExposed (fref))
1286 if (sRef_isPossiblyDead (fref) || sRef_isRelDef (fref))
1288 if (exprNode_isDefined (fexp))
1291 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1292 message ("Only storage %q (type %s) derived from %s "
1293 "may not have been released: %s",
1294 sRef_unparse (fref),
1295 ctype_unparse (sRef_getType (fref)),
1296 dscCode_unparse (desc),
1297 exprNode_unparse (fexp)),
1303 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1305 ("Only storage %q (type %s) derived from %s "
1306 "may not have been released",
1307 sRef_unparse (fref),
1308 ctype_unparse (sRef_getType (fref)),
1309 dscCode_unparse (desc)),
1313 sRef_kill (fref, loc); /* prevent further errors */
1317 if (sRef_isStateUndefined (fref))
1323 if (exprNode_isDefined (fexp))
1327 message ("Only storage %q (type %s) derived from %s "
1328 "is not released (memory leak): %s",
1329 sRef_unparse (fref),
1330 ctype_unparse (sRef_getType (fref)),
1331 dscCode_unparse (desc),
1332 exprNode_unparse (fexp)),
1339 message ("Only storage %q (type %s) derived from %s "
1340 "is not released (memory leak)",
1341 sRef_unparse (fref),
1342 ctype_unparse (sRef_getType (fref)),
1343 dscCode_unparse (desc)),
1352 if (sRef_isAnyDefined (fref) || sRef_isDead (fref)
1353 || (sRef_isPdefined (fref)
1354 && sRefSet_isEmpty (sRef_derivedFields (fref))))
1360 if (ctype_isPointer (ct))
1362 sRef fptr = sRef_constructDeadDeref (fref);
1363 bool res = checkCompletelyDestroyed (fexp, fptr, FALSE, loc,
1368 else if (ctype_isArray (ct))
1370 if ((sRef_isStateUnknown (fref) || sRef_isAllocated (fref))
1371 && !sRef_hasDerived (fref))
1374 ** Bogosity necessary to prevent infinite depth.
1381 sRef farr = sRef_constructDeadDeref (fref);
1383 return (checkCompletelyDestroyed (fexp, farr, FALSE, loc,
1387 else if (ctype_isStruct (ct))
1390 ** for structures, each field must be completely destroyed
1394 uentryList fields = ctype_getFields (ct);
1396 if (depth >= MAXDEPTH)
1398 llquietbug (message ("checkCompletelyDestroyed (fields): too deep: %s / %q",
1399 exprNode_unparse (fexp),
1400 sRef_unparseFull (fref)));
1406 uentryList_elements (fields, ue)
1408 sRef field = sRef_makeField (fref, uentry_rawName (ue));
1411 ** note order of && operands --- want to report multiple errors
1414 isOk = (checkCompletelyDestroyed (fexp, field, FALSE, loc,
1417 } end_uentryList_elements;
1429 checkReturnTransfer (exprNode fexp, uentry rval)
1431 sRef uref = uentry_getSref (rval);
1432 sRef rref = sRef_makeNew (sRef_getType (uref), uref, cstring_undefined);
1434 if (sRef_isStateSpecial (rref))
1436 uentry fcn = context_getHeader ();
1437 sRef fref = exprNode_getSref (fexp);
1438 specialClauses clauses = uentry_getSpecialClauses (fcn);
1440 specialClauses_postElements (clauses, cl)
1442 sRefSet refs = specialClause_getRefs (cl);
1443 sRefTest tst = specialClause_getPostTestFunction (cl);
1444 sRefMod modf = specialClause_getReturnEffectFunction (cl);
1446 sRefSet_elements (refs, el)
1448 sRef base = sRef_getRootBase (el);
1450 if (sRef_isResult (base))
1452 sRef sr = sRef_fixBase (el, fref);
1454 if (tst != NULL && !(tst (sr)))
1457 (specialClause_postErrorCode (cl),
1458 message ("%s storage %q corresponds to "
1459 "storage listed in %q clause: %s",
1460 specialClause_postErrorString (cl, sr),
1462 specialClause_unparseKind (cl),
1463 exprNode_unparse (fexp)),
1464 exprNode_loc (fexp)))
1466 sRefShower ss = specialClause_getPostTestShower (cl);
1477 modf (sr, exprNode_loc (fexp));
1483 ** Non-results are checked in exit scope.
1486 } end_sRefSet_elements ;
1487 } end_specialClauses_postElements ;
1489 (void) checkTransfer (fexp, fref,
1490 exprNode_undefined, rref,
1491 exprNode_loc (fexp), TT_FCNRETURN);
1495 if (ctype_isRealSU (exprNode_getType (fexp)))
1497 sRef fref = exprNode_getSref (fexp);
1499 checkStructTransfer (exprNode_undefined, rref,
1501 exprNode_loc (fexp),
1506 (void) checkTransfer (fexp, exprNode_getSref (fexp),
1507 exprNode_undefined, rref,
1508 exprNode_loc (fexp), TT_FCNRETURN);
1514 checkPassSpecialClauses (uentry ue, exprNode fexp, sRef fref, int argno)
1516 specialClauses clauses = uentry_getSpecialClauses (ue);
1518 DPRINTF (("Check pass special: %s / %s",
1519 exprNode_unparse (fexp), sRef_unparseFull (fref)));
1521 specialClauses_preElements (clauses, cl)
1523 sRefSet refs = specialClause_getRefs (cl);
1524 sRefTest tst = specialClause_getPreTestFunction (cl);
1525 sRefMod modf = specialClause_getEffectFunction (cl);
1527 sRefSet_elements (refs, el)
1529 sRef base = sRef_getRootBase (el);
1531 if (sRef_isResult (base))
1533 ; /* nothing to check before */
1535 else if (sRef_isParam (base))
1537 if (sRef_getParam (base) == argno - 1)
1541 DPRINTF (("Fix base: %s / %s",
1542 sRef_unparseFull (el),
1543 sRef_unparseFull (fref)));
1545 sb = sRef_fixBase (el, fref);
1547 if (tst != NULL && !(tst(sb)))
1550 (specialClause_preErrorCode (cl),
1551 message ("%s storage %qcorresponds to "
1552 "storage listed in %q clause of "
1553 "called function: %s",
1554 specialClause_preErrorString (cl, sb),
1555 sRef_unparseOpt (sb),
1556 specialClause_unparseKind (cl),
1557 exprNode_unparse (fexp)),
1558 exprNode_loc (fexp));
1563 DPRINTF (("Fixing: %s", sRef_unparseFull (sb)));
1564 modf (sb, exprNode_loc (fexp));
1565 DPRINTF (("==> %s", sRef_unparseFull (sb)));
1573 } end_sRefSet_elements ;
1574 } end_specialClauses_preElements ;
1576 DPRINTF (("After: %s", sRef_unparseFull (fref)));
1580 ** should not modify arg
1584 checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
1585 /*@dependent@*/ exprNode fcn, int argno, int totargs)
1587 sRef tref = uentry_getSref (arg);
1588 sRef fref = exprNode_getSref (fexp);
1590 bool isPartial = FALSE;
1591 bool isImpOut = FALSE;
1592 ctype ct = uentry_getType (arg);
1594 DPRINTF (("Check pass: %s -> %s",
1595 sRef_unparseFull (fref),
1596 sRef_unparseFull (tref)));
1600 atNumArgs = totargs;
1602 if (ctype_isElips (ct))
1607 if (!ctype_isElips (ct) &&
1608 (ctype_isVoidPointer (ct) && uentry_isOut (arg) && sRef_isOnly (tref)))
1610 if (ctype_isRealAP (ct))
1612 if (sRef_aliasCheckSimplePred (sRef_isDead, fref))
1616 message ("Dead storage %qpassed as out parameter: %s",
1617 sRef_unparseOpt (fref),
1618 exprNode_unparse (fexp)),
1619 exprNode_loc (fexp)))
1621 if (sRef_isDead (fref))
1623 sRef_showStateInfo (fref);
1627 sRef_setAllocated (fref, exprNode_loc (fexp));
1629 else if (context_getFlag (FLG_STRICTUSERELEASED)
1630 && sRef_aliasCheckSimplePred (sRef_isPossiblyDead, fref))
1633 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1634 message ("Possibly dead storage %qpassed as out parameter: %s",
1635 sRef_unparseOpt (fref),
1636 exprNode_unparse (fexp)),
1637 exprNode_loc (fexp)))
1639 if (sRef_isPossiblyDead (fref))
1641 sRef_showStateInfo (fref);
1645 sRef_setAllocated (fref, exprNode_loc (fexp));
1647 else if (sRef_aliasCheckSimplePred (sRef_isStateUndefined, fref)
1648 || sRef_aliasCheckSimplePred (sRef_isUnuseable, fref))
1652 message ("Unallocated storage %qpassed as out parameter: %s",
1653 sRef_unparseOpt (fref),
1654 exprNode_unparse (fexp)),
1655 exprNode_loc (fexp));
1657 sRef_setAllocated (fref, exprNode_loc (fexp));
1665 (void) checkCompletelyDestroyed (fexp, fref, TRUE, exprNode_loc (fexp),
1668 /* make it defined now, so checkTransfer is okay */
1669 sRef_setDefined (fref, exprNode_loc (fexp));
1671 else if (uentry_isOut (arg))
1673 if (ctype_isRealAP (ct)
1674 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1678 message ("Unallocated storage %qpassed as out parameter: %s",
1679 sRef_unparseOpt (fref),
1680 exprNode_unparse (fexp)),
1681 exprNode_loc (fexp));
1682 sRef_setAllocated (fref, exprNode_loc (fexp));
1686 else if (uentry_isPartial (arg))
1688 if (ctype_isRealAP (ct)
1689 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1693 message ("Unallocated storage %qpassed as partial parameter: %s",
1694 sRef_unparseOpt (fref),
1695 exprNode_unparse (fexp)),
1696 exprNode_loc (fexp));
1697 sRef_setAllocated (fref, exprNode_loc (fexp));
1701 else if (uentry_isStateSpecial (arg))
1703 uentry ue = exprNode_getUentry (fcn);
1705 if (ctype_isRealAP (ct)
1706 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1710 message ("Unallocated storage %qpassed as special parameter: %s",
1711 sRef_unparseOpt (fref),
1712 exprNode_unparse (fexp)),
1713 exprNode_loc (fexp));
1714 sRef_setAllocated (fref, exprNode_loc (fexp));
1717 if (uentry_hasSpecialClauses (ue))
1719 checkPassSpecialClauses (ue, fexp, fref, argno);
1724 else if (sRef_isStateDefined (tref))
1726 exprNode_checkUseParam (fexp);
1730 if (isSpec || (!context_getFlag (FLG_IMPOUTS)))
1732 exprNode_checkUseParam (fexp);
1736 if (!sRef_isMacroParamRef (fref)
1737 && (ctype_isRealAP (ct)))
1739 if (sRef_isAddress (fref))
1741 if (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref))
1746 ("Unallocated address %qpassed as implicit "
1747 "out parameter: %s",
1748 sRef_unparseOpt (fref),
1749 exprNode_unparse (fexp)),
1750 exprNode_loc (fexp));
1751 sRef_setAllocated (fref, exprNode_loc (fexp));
1755 /* yes, I really mean this! */
1756 tref = sRef_copy (tref);
1757 sRef_setAllocated (tref, exprNode_loc (fexp));
1764 exprNode_checkUseParam (fexp);
1769 if (sRef_isNew (fref))
1771 alkind tkind = sRef_getAliasKind (tref);
1773 if ((sRef_isFresh (fref) || sRef_isOnly (fref))
1774 && !alkind_isOnly (tkind)
1775 && !alkind_isKeep (tkind)
1776 && !alkind_isOwned (tkind)
1777 && !alkind_isError (tkind)
1778 && !uentry_isReturned (arg))
1783 message ("New fresh storage %qpassed as %s (not released): %s",
1784 sRef_unparseOpt (fref),
1785 alkind_unparse (sRef_getAliasKind (tref)),
1786 exprNode_unparse (fexp)),
1787 exprNode_loc (fexp));
1791 if (sRef_isNewRef (fref) && !sRef_isKillRef (tref))
1793 alkind ak = sRef_getAliasKind (tref);
1795 if (!alkind_isError (ak))
1799 message ("New reference %qpassed as %s (not released): %s",
1800 sRef_unparseOpt (fref),
1801 alkind_unparse (sRef_getAliasKind (tref)),
1802 exprNode_unparse (fexp)),
1803 exprNode_loc (fexp));
1809 (void) checkTransfer (fexp, exprNode_getSref (fexp),
1810 exprNode_undefined, tref,
1811 exprNode_loc (fexp), TT_FCNPASS);
1814 fref = exprNode_getSref (fexp);
1816 if (isOut && !sRef_isDead (fref) && !sRef_isPossiblyDead (fref))
1820 if (ctype_isRealAP (sRef_getType (fref)))
1822 base = sRef_makePointer (fref);
1831 exprNode_checkMSet (fexp, base);
1835 exprNode_checkSet (fexp, base);
1838 if (sRef_isValid (base))
1842 sRef_clearDerived (base);
1843 sRef_setDefined (base, exprNode_loc (fexp));
1844 usymtab_clearAlias (base);
1845 sRef_setNullUnknown (base, exprNode_loc (fexp));
1851 if (sRef_isValid (fref))
1853 sRef_setPartial (fref, exprNode_loc (fexp));
1857 atFunction = exprNode_undefined;
1861 /* need to fixup here: derived refs could be bogus */
1862 /* (better to change sRef to not add derivs for "protected" ref) */
1864 uentry_fixupSref (arg);
1868 DPRINTF (("Check pass: ==> %s",
1869 sRef_unparseFull (fref)));
1873 checkGlobReturn (uentry glob)
1875 sRef_protectDerivs ();
1876 checkGlobTrans (glob, TT_GLOBRETURN);
1877 sRef_clearProtectDerivs ();
1880 void checkParamReturn (uentry actual)
1882 checkLeaveTrans (actual, TT_PARAMRETURN);
1885 void checkLoseRef (uentry actual)
1887 checkLeaveTrans (actual, TT_LEAVETRANS);
1891 checkLeaveTrans (uentry actual, transferKind transferType)
1893 sRef aref = uentry_getSref (actual);
1894 sRef origref = uentry_getOrigSref (actual);
1896 if (transferType == TT_PARAMRETURN
1897 && (sRef_isKeep (origref) || sRef_isOnly (origref)
1898 || sRef_isOwned (origref)))
1900 /* caller cannot use, nothing to check */
1904 if (sRef_isNSLocalVar (origref))
1910 (void) checkCompletelyDefined (exprNode_undefined, aref,
1911 exprNode_undefined, origref,
1913 g_currentloc, transferType,
1920 checkGlobTrans (uentry glob, transferKind type)
1922 sRef eref = uentry_getOrigSref (glob);
1924 (void) checkCompletelyDefined (exprNode_undefined, uentry_getSref (glob),
1925 exprNode_undefined, eref,
1927 g_currentloc, type, 0, TRUE);
1931 ** For lhs of assignment, alias kind is set from basic type.
1936 fixAssignLhs (sRef s)
1938 sRef_resetStateComplete (s);
1941 static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srhs,
1945 ctype st = ctype_realType (sRef_getType (srhs));
1947 if (ctype_isSU (st) && ctype_isRealSU (sRef_getType (slhs))
1948 && ctype_match (sRef_getType (slhs), st))
1950 if (tt == TT_DOASSIGN && sRef_isStateDefined (srhs))
1952 sRef_setDefinedComplete (slhs, loc);
1955 if (sRef_isDependent (slhs)
1956 || sRef_isObserver (slhs)
1957 || sRef_isExposed (slhs))
1963 if (sRef_isLocalVar (slhs)
1964 && sRef_isGlobal (sRef_getRootBase (srhs)))
1966 sRef_setDependent (slhs, exprNode_loc (lhs));
1970 if (ctype_isUnion (st))
1972 sRef_setDefState (slhs, sRef_getDefState (srhs),
1973 exprNode_loc (lhs));
1975 sRefSet_realElements (sRef_derivedFields (srhs), sr)
1977 if (sRef_isField (sr))
1979 cstring fieldname = sRef_getField (sr);
1980 sRef lfld = sRef_makeField (slhs, fieldname);
1982 (void) checkTransfer (rhs, sr, lhs, lfld,
1983 exprNode_loc (lhs), tt);
1985 } end_sRefSet_realElements ;
1989 uentryList fields = ctype_getFields (st);
1991 uentryList_elements (fields, field)
1993 sRef rfld = sRef_makeField (srhs, uentry_rawName (field));
1994 sRef lfld = sRef_makeField (slhs, uentry_rawName (field));
1995 (void) checkTransfer (rhs, rfld, lhs, lfld, exprNode_loc (lhs), tt);
1996 } end_uentryList_elements ;
1999 if (sRef_isOnly (srhs))
2001 sRef_setKeptComplete (srhs, loc);
2009 checkInitTransfer (exprNode lhs, exprNode rhs)
2011 sRef slhs = exprNode_getSref (lhs);
2013 if (sRef_isGlobal (slhs) || (!sRef_isCvar (slhs)))
2015 (void) checkTransfer (rhs, exprNode_getSref (rhs),
2016 lhs, slhs, exprNode_loc (rhs), TT_GLOBINIT);
2020 checkAssignTransfer (lhs, rhs);
2025 checkAssignTransfer (exprNode lhs, exprNode rhs)
2027 sRef slhs = exprNode_getSref (lhs);
2028 sRef srhs = exprNode_getSref (rhs);
2029 sRef base = sRef_getBaseSafe (slhs);
2031 struct _bbufinfo bs;
2033 DPRINTF (("Check assign: %s = %s", exprNode_unparse (lhs),
2034 exprNode_unparse (rhs)));
2035 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2036 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2038 if (ctype_isRealSU (sRef_getType (srhs)))
2040 checkStructTransfer (lhs, slhs, rhs, srhs, exprNode_loc (lhs), TT_FIELDASSIGN);
2044 (void) checkTransfer (rhs, srhs, lhs, slhs,
2045 exprNode_loc (lhs), TT_DOASSIGN);
2048 if (sRef_isConst (srhs) && sRef_isLocalState (srhs))
2050 /* constants can match anything (e.g., NULL) */
2051 sRef_setAliasKind (slhs, AK_ERROR, fileloc_undefined);
2054 if (sRef_isValid (base) && sRef_isStateDefined (base))
2056 sRef_setPdefined (base, g_currentloc);
2059 if (sRef_isPartial (srhs))
2061 sRef_setPartial (slhs, exprNode_loc (rhs));
2065 ns = sRef_getNullState (srhs);
2067 if (nstate_possiblyNull (ns))
2069 if (usymtab_isGuarded (srhs))
2075 sRef_setNullStateInnerComplete (slhs, ns, exprNode_loc (rhs));
2077 if (sRef_isExposed (srhs) || sRef_isObserver (srhs))
2079 sRef_setExKind (slhs, sRef_getExKind (srhs), exprNode_loc (rhs));
2082 /* We put the function to transfer NT states */
2083 bs = sRef_getNullTerminatedState (srhs);
2084 sRef_setNullTerminatedStateInnerComplete (slhs, bs, exprNode_loc (rhs));
2085 DPRINTF (("Done transfer: %s", sRef_unparseFull (slhs)));
2089 checkTransferNullAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2090 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2091 fileloc loc, transferKind transferType)
2093 alkind tkind = sRef_getAliasKind (tref);
2094 ctype ttyp = ctype_realType (sRef_getType (tref));
2096 if (ctype_isUnknown (ttyp))
2098 ttyp = exprNode_getType (texp);
2100 if (ctype_isUnknown (ttyp))
2102 ttyp = exprNode_getType (fexp);
2104 if (ctype_isUnknown (ttyp))
2106 ttyp = sRef_getType (fref);
2111 if (ctype_isFunction (ttyp) && (transferType == TT_FCNRETURN))
2113 ttyp = ctype_returnValue (ttyp);
2117 ** check for null (don't need to check aliases??)
2120 if (sRef_possiblyNull (fref)
2121 && !usymtab_isGuarded (fref)
2122 && ctype_isRealAP (ttyp))
2124 if (!alkind_isLocal (tkind) && !alkind_isFresh (tkind)
2125 && !sRef_perhapsNull (tref)
2126 && !(transferType == TT_DOASSIGN))
2128 if (transferType == TT_GLOBINIT)
2132 message ("%s %q initialized to %s value: %q",
2133 sRef_getScopeName (tref),
2134 sRef_unparse (tref),
2135 sRef_nullMessage (fref),
2136 generateText (fexp, texp, tref, transferType)),
2139 sRef_showNullInfo (fref);
2140 sRef_setNullError (tref);
2146 ((transferType == TT_FCNPASS) ? FLG_NULLPASS : FLG_NULLRET,
2147 message ("%q storage %q%s: %q",
2148 cstring_capitalize (sRef_nullMessage (fref)),
2149 sRef_unparseOpt (fref),
2150 transferNullMessage (transferType),
2151 generateText (fexp, texp, tref, transferType)),
2154 sRef_showNullInfo (fref);
2155 sRef_setNullError (fref);
2168 checkTransferAssignAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2169 sRef tref, exprNode texp, bool tfix,
2170 fileloc loc, transferKind transferType)
2172 alkind tkind = sRef_getAliasKind (tref);
2175 ** Assignment to same --- no errors, or state changes.
2176 ** This can happen when returned params are used.
2179 if (sRef_sameName (fref, tref))
2181 sRef_copyState (tref, fref);
2185 if ((alkind_isOnly (tkind) || alkind_isFresh (tkind)
2186 || alkind_isNewRef (tkind) || alkind_isOwned (tkind))
2187 && !(sRef_isDead (tref)
2188 || sRef_isStateUndefined (tref)
2189 || sRef_isUnuseable (tref)
2190 || sRef_isPartial (tref)
2191 || sRef_definitelyNull (tref)
2192 || sRef_isStackAllocated (tref)
2193 || sRef_isAllocIndexRef (tref))
2194 && !(sRef_same (fref, tref)) /* okay to assign to self (returned params) */
2195 && !(usymtab_isProbableNull (tref)))
2197 if (context_getFlag (FLG_MUSTFREE))
2199 if (canLoseReference (tref, loc))
2205 if (sRef_hasLastReference (tref))
2209 message ("Last reference %q to %s storage %qnot released "
2210 "before assignment: %q",
2211 sRef_unparse (tref),
2212 alkind_unparse (tkind),
2213 sRef_unparseOpt (sRef_getAliasInfoRef (tref)),
2214 generateText (fexp, texp, tref, transferType)),
2217 sRef_showRefLost (tref);
2222 if (context_inGlobalScope ())
2224 /* no errors for static initializations */
2229 ** don't report this error for a[i], since it could
2230 ** be a new element.
2233 if (alkind_isNewRef (tkind))
2238 ("%q %qnot released before assignment: %q",
2240 (alkind_isKillRef (sRef_getOrigAliasKind (tref))
2241 ? "Kill reference parameter" : "New reference"),
2242 sRef_unparseOpt (tref),
2243 generateText (fexp, texp, tref, transferType)),
2246 sRef_showAliasInfo (tref);
2247 sRef_setAliasKind (tref, AK_ERROR, loc);
2251 (!(sRef_isUnknownArrayFetch (tref)
2252 && !context_getFlag (FLG_STRICTDESTROY))
2253 && !sRef_isUnionField (tref)
2254 && !sRef_isRelDef (tref)
2258 ("%s storage %qnot released before assignment: %q",
2259 alkind_capName (tkind),
2260 sRef_unparseOpt (tref),
2261 generateText (fexp, texp, tref, transferType)),
2264 sRef_showAliasInfo (tref);
2276 fixAssignLhs (tref);
2278 if (sRef_isRefCounted (tref)) /* tkind might not be correct now */
2280 if (sRef_isNewRef (fref))
2282 sRef_setAliasKind (tref, AK_NEWREF, loc);
2284 else if (sRef_isConst (fref))
2286 /* for now, constants are not ref counted */
2287 sRef_setAliasKind (tref, AK_ERROR, loc);
2294 if (!sRef_isNSLocalVar (tref)
2295 && sRef_isRefCounted (fref)
2296 && sRef_isStateDefined (fref))
2300 message ("New reference %qto reference counted storage: %q",
2301 sRef_unparseOpt (tref),
2302 generateText (fexp, texp, tref, transferType)),
2308 ** Not for structures and unions, since assignments copy.
2311 if (sRef_isStack (fref)
2312 && !ctype_isSU (ctype_realType (sRef_getType (fref))))
2314 sRef_setAliasKindComplete (tref, AK_STACK, loc);
2317 if (sRef_isNSLocalVar (tref)
2318 && !sRef_isOwned (tref) /*< should only apply to static >*/
2319 && ctype_isMutable (sRef_getType (tref)))
2321 if (sRef_isOnly (fref) && sRef_isNew (fref))
2325 sRef_setFresh (tref, loc);
2332 ** requires sRef_isOnly (fref)
2336 checkOnlyTransferAux (sRef fref, exprNode fexp, bool ffix,
2337 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2338 fileloc loc, transferKind transferType)
2340 alkind tkind = sRef_getAliasKind (tref);
2342 if (sRef_isExposed (tref) || sRef_isObserver (tref))
2344 if (transferType == TT_FCNRETURN && sRef_isNew (fref)
2345 && !alkind_isError (tkind))
2349 message ("Only storage %q%q (will not be released): %q",
2350 sRef_unparseOpt (fref),
2351 transferErrorMessage (transferType, tkind),
2352 generateText (fexp, texp, tref, transferType)),
2355 sRef_showAliasInfo (fref);
2359 /* no errors for exposed transfers (is this good enough?) */
2361 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind) || alkind_isOwned (tkind))
2365 else if ((transferType == TT_FCNPASS)
2366 && (alkind_isUnknown (tkind)
2367 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2369 if (sRef_isFresh (fref)
2370 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2372 if (!ffix) sRef_setAliasKind (fref, AK_UNKNOWN, loc);
2375 else if (alkind_isLocal (tkind)
2376 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2378 if ((transferType == TT_DOASSIGN)
2379 && sRef_isNew (fref)
2380 && sRef_isOnly (fref))
2384 if (alkind_isUnknown (tkind)
2385 && sRef_isGlobal (sRef_getRootBase (tref)))
2388 (FLG_ONLYUNQGLOBALTRANS,
2389 message ("Only storage %q%q: %q",
2390 sRef_unparseOpt (fref),
2391 transferErrorMessage (transferType, tkind),
2392 generateText (fexp, texp, tref, transferType)),
2395 sRef_showAliasInfo (fref);
2396 sRef_setAliasKind (tref, AK_ERROR, loc);
2401 if (!error && !ffix)
2403 sRef_setFresh (tref, loc);
2408 if (alkind_isLocal (tkind))
2410 if (sRef_sameName (tref, fref))
2412 ; /* don't set this --- corresponds to return transfer */
2417 ** Don't set local to dependent. Error will
2418 ** be detected through aliasing. Except for
2422 if (!tfix && sRef_isThroughArrayFetch (fref)
2423 && context_getFlag (FLG_DEPARRAYS))
2425 sRef_setDependent (tref, loc);
2433 message ("Only storage %q%q: %q",
2434 sRef_unparseOpt (fref),
2435 transferErrorMessage (transferType, tkind),
2436 generateText (fexp, texp, tref, transferType)),
2439 sRef_showAliasInfo (fref);
2446 if (alkind_isError (tkind)
2447 || (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT)))
2449 flagcode_recordSuppressed (FLG_ONLYTRANS);
2453 if ((alkind_isKept (tkind) || alkind_isStack (tkind)
2454 || alkind_isDependent (tkind))
2455 && sRef_isNSLocalVar (tref))
2463 message ("Only storage %q%q: %q",
2464 sRef_unparseOpt (fref),
2465 transferErrorMessage (transferType, tkind),
2466 generateText (fexp, texp, tref, transferType)),
2469 sRef_showAliasInfo (fref);
2474 if (transferType == TT_DOASSIGN)
2477 ** alias kind unknown to suppress future messages
2480 if (!ffix && sRef_isNSLocalVar (sRef_getRootBase (fref)))
2482 sRef_clearAliasKind (fref);
2489 ** ??? same as checkOnly ?
2493 checkOwnedTransferAux (sRef fref, exprNode fexp, bool ffix,
2494 sRef tref, exprNode texp, bool tfix,
2495 fileloc loc, transferKind transferType)
2497 alkind tkind = sRef_getAliasKind (tref);
2499 if (sRef_isExposed (tref) || sRef_isObserver (tref))
2501 if (transferType == TT_FCNRETURN && sRef_isNew (fref))
2505 message ("Owned storage %q%q (will not be released): %q",
2506 sRef_unparseOpt (fref),
2507 transferErrorMessage (transferType, tkind),
2508 generateText (fexp, texp, tref, transferType)),
2511 sRef_showAliasInfo (fref);
2515 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind)
2516 || alkind_isDependent (tkind)
2517 || alkind_isOwned (tkind))
2521 else if (alkind_isLocal (tkind)
2522 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2524 if ((transferType == TT_DOASSIGN)
2525 && sRef_isNew (fref) && sRef_isOnly (fref))
2529 sRef_setFresh (tref, loc);
2536 else if ((transferType == TT_FCNPASS)
2537 && (alkind_isUnknown (tkind)
2538 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2540 if (sRef_isFresh (fref)
2541 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2543 if (!ffix) { sRef_clearAliasKind (fref); }
2548 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2550 flagcode_recordSuppressed (FLG_OWNEDTRANS);
2554 if (alkind_isKept (tkind) && sRef_isNSLocalVar (tref))
2562 message ("Owned storage %q%q: %q",
2563 sRef_unparseOpt (fref),
2564 transferErrorMessage (transferType, tkind),
2565 generateText (fexp, texp, tref, transferType)),
2570 if (transferType == TT_DOASSIGN)
2573 ** alias kind unknown to suppress future messages
2576 if (!ffix) { sRef_clearAliasKind (fref); }
2582 checkFreshTransferAux (sRef fref, exprNode fexp, bool ffix,
2583 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2584 fileloc loc, transferKind transferType)
2586 alkind tkind = sRef_getAliasKind (tref);
2589 ** error to return fresh as non-only
2592 if (transferType == TT_FCNRETURN
2593 && !(alkind_isOnly (tkind) || alkind_isNewRef (tkind)))
2595 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2597 flagcode_recordSuppressed (FLG_NEWREFTRANS);
2601 if (alkind_isError (tkind))
2605 sRef_killComplete (fref, loc);
2608 else if (alkind_isRefCounted (tkind))
2613 ("New reference returned without newref qualifier: %q",
2614 generateText (fexp, texp, tref, transferType)),
2617 sRef_showAliasInfo (fref);
2618 sRef_killComplete (fref, loc);
2625 message ("Fresh storage %q (should be only): %q",
2626 transferErrorMessage (transferType, tkind),
2627 generateText (fexp, texp, tref, transferType)),
2630 sRef_showAliasInfo (fref);
2631 sRef_killComplete (fref, loc);
2638 ** Okay to assign fresh to only, shared or unqualified.
2640 ** should generate other errors?
2643 if (alkind_isOnly (tkind))
2645 if (transferType == TT_DOASSIGN && !sRef_isGlobal (tref))
2649 if (!sRef_isNSLocalVar (tref))
2651 sRef_setKeptComplete (fref, loc);
2657 if (sRef_isConst (fref))
2665 sRef_killComplete (fref, loc);
2670 else if (alkind_isOwned (tkind))
2674 sRef_setDependentComplete (fref, loc);
2677 else if (alkind_isRefCounted (tkind)
2678 && (transferType == TT_FCNRETURN) && sRef_isFresh (fref))
2682 sRef_killComplete (fref, loc);
2685 else if (alkind_isKeep (tkind))
2689 if (!sRef_isNSLocalVar (tref))
2691 sRef_setKeptComplete (fref, loc);
2695 else if (alkind_isShared (tkind))
2697 if (!ffix) { sRef_setShared (fref, loc); }
2699 else if (alkind_isLocal (tkind) || alkind_isUnknown (tkind))
2701 if (transferType == TT_DOASSIGN || transferType == TT_FCNRETURN)
2704 ** local shares fresh. Make it owned/dependent.
2709 sRef_setOwned (tref, loc);
2714 sRef_setDependentComplete (fref, loc);
2717 /* NO! sRef_clearAliasKind (fref); */
2721 if (context_getFlag (FLG_PASSUNKNOWN))
2723 sRef_clearAliasKind (fref);
2734 checkTransferExposure (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2735 sRef tref, exprNode texp, bool tfix,
2737 transferKind transferType)
2739 alkind fkind = sRef_getAliasKind (fref);
2740 alkind tkind = sRef_getAliasKind (tref);
2741 exkind tekind = sRef_getExKind (tref);
2743 if (sRef_isObserver (fref) && ctype_isMutable (sRef_getType (fref)))
2746 ** observer -> exposed or observer
2750 ** observer -> temp is okay [NO! really? only in function calls]
2753 if (sRef_isExposed (tref) || sRef_isObserver (tref)
2754 || alkind_isLocal (tkind))
2758 if ((transferType == TT_DOASSIGN) && alkind_isLocal (tkind))
2760 if (!tfix) { sRef_setAliasKindComplete (tref, fkind, loc); }
2765 if (transferType == TT_FCNRETURN
2766 || transferType == TT_DOASSIGN
2767 || transferType == TT_FIELDASSIGN
2768 || transferType == TT_GLOBINIT)
2770 bool hasError = FALSE;
2772 if (exprNode_isStringLiteral (fexp)
2773 && transferType == TT_GLOBINIT)
2775 hasError = optgenerror
2777 message ("Read-only string literal storage %q%q: %q",
2778 sRef_unparseOpt (fref),
2779 transferErrorExpMessage (transferType, tekind),
2780 generateText (fexp, texp, tref, transferType)),
2783 sRef_setAliasKind (fref, AK_ERROR, fileloc_undefined);
2787 if ((transferType == TT_DOASSIGN
2788 || transferType == TT_FIELDASSIGN)
2789 && (sRef_isNSLocalVar (tref)
2790 || (exprNode_isStringLiteral (fexp)
2791 && ctype_isRealArray (exprNode_getType (texp)))))
2793 ; /* No error for local assignment or assignment
2794 to static array (copies string). */
2798 if (exprNode_isStringLiteral (fexp))
2800 hasError = optgenerror
2803 ("Read-only string literal storage %q%q: %q",
2804 sRef_unparseOpt (fref),
2805 transferErrorExpMessage (transferType, tekind),
2806 generateText (fexp, texp, tref, transferType)),
2813 hasError = optgenerror
2816 ("Observer storage %q%q: %q",
2817 sRef_unparseOpt (fref),
2818 transferErrorExpMessage (transferType, tekind),
2819 generateText (fexp, texp, tref, transferType)),
2827 if (transferType != TT_GLOBINIT)
2829 sRef_showExpInfo (fref);
2830 sRef_setAliasKind (tref, AK_ERROR, loc);
2835 if (transferType == TT_DOASSIGN && !tfix)
2837 DPRINTF (("Setting unknown!"));
2838 /* sRef_setAliasKind (tref, AK_ERROR, loc); */
2842 else /* TT_FCNPASS */
2844 llassert (transferType == TT_FCNPASS);
2846 if (alkind_isTemp (tkind)
2847 || alkind_isDependent (tkind)
2848 || alkind_isRefCounted (tkind))
2854 if (!alkind_isError (tkind))
2858 message ("Observer storage %q%q: %q",
2859 sRef_unparseOpt (fref),
2860 transferErrorMessage (transferType, tkind),
2861 generateText (fexp, texp, tref, transferType)),
2864 sRef_showExpInfo (fref);
2865 sRef_clearAliasState (fref, loc);
2872 else if (sRef_isExposed (fref) && ctype_isMutable (sRef_getType (fref)))
2874 if (transferType == TT_FCNRETURN)
2876 if (!(sRef_isExposed (tref) || sRef_isObserver (tref)
2877 || sRef_isParam (fref)))
2881 message ("Exposed storage %q%q: %q",
2882 sRef_unparseOpt (fref),
2883 transferErrorExpMessage (transferType, tekind),
2884 generateText (fexp, texp, tref, transferType)),
2887 sRef_showExpInfo (fref);
2891 else if (transferType == TT_FCNPASS)
2893 if (!(sRef_isExposed (tref)
2894 || sRef_isObserver (tref)
2895 || (alkind_isUnknown (tkind)
2896 || alkind_isDependent (tkind)
2897 || alkind_isTemp (tkind)
2898 || alkind_isKillRef (tkind)
2899 || alkind_isRefCounted (tkind))))
2901 if (alkind_isUnique (tkind) || alkind_isError (tkind))
2908 message ("Exposed storage %q%q: %q",
2909 sRef_unparseOpt (fref),
2910 transferErrorMessage (transferType, tkind),
2911 generateText (fexp, texp, tref, transferType)),
2914 sRef_showExpInfo (fref);
2915 sRef_clearAliasState (fref, loc);
2925 else if (transferType == TT_DOASSIGN)
2927 if (!(sRef_isExposed (tref)
2928 || !sRef_isCvar (tref)
2929 || (alkind_isUnknown (tkind)
2930 || alkind_isDependent (tkind)
2931 || alkind_isRefCounted (tkind)
2932 || alkind_isNewRef (tkind)
2933 || alkind_isFresh (tkind)
2934 || alkind_isLocal (tkind))))
2938 message ("Exposed storage %q%q: %q",
2939 sRef_unparseOpt (fref),
2940 transferErrorExpMessage (transferType, tekind),
2941 generateText (fexp, texp, tref, transferType)),
2944 sRef_showExpInfo (fref);
2947 if (!tfix) { sRef_setExposed (tref, loc); }
2951 llassert (transferType == TT_GLOBPASS
2952 || transferType == TT_GLOBRETURN
2953 || transferType == TT_PARAMRETURN
2954 || transferType == TT_LEAVETRANS
2955 || transferType == TT_GLOBINIT);
2965 ** returns TRUE if there is no error reported
2967 ** if fixt, don't change tref (except if error reported.)
2968 ** if fixf, don't change fref (except if error reported.)
2972 checkTransferAux (exprNode fexp, sRef fref, bool ffix,
2973 exprNode texp, sRef tref, bool tfix,
2974 fileloc loc, transferKind transferType)
2978 bool isassign = (transferType == TT_DOASSIGN);
2979 bool isfieldassign = (transferType == TT_FIELDASSIGN);
2980 bool iseitherassign = isassign || (transferType == TT_FIELDASSIGN);
2981 bool isfcnpass = (transferType == TT_FCNPASS);
2982 bool isfcnreturn = (transferType == TT_FCNRETURN);
2986 /*start modification David Larochelle */
2991 checkTransferNullTerminatedAux (fref, fexp, ffix, tref, texp, tfix,
2994 /*end modification */
2999 checkTransferNullAux (fref, fexp, ffix, tref, texp, tfix,
3006 checkTransferAssignAux (fref, fexp, ffix, tref, texp, tfix,
3011 ** Check for definition
3015 ** errors passing out params already detected in checkAnyCall
3023 || (!sRef_isNSLocalVar (tref)
3024 && (sRef_isAnyDefined (tref) || !sRef_stateKnown (tref))))
3028 if (!ynm_toBoolRelaxed
3029 (checkCompletelyDefined (fexp, fref, texp, tref,
3031 loc, transferType, 0, TRUE)))
3039 if (defok && iseitherassign)
3041 sRef_setDefState (tref, sRef_getDefState (fref), loc);
3051 checkTransferExposure (fref, fexp, ffix, tref, texp, tfix,
3054 fkind = sRef_getAliasKind (fref);
3055 tkind = sRef_getAliasKind (tref);
3061 if (alkind_isOnly (fkind))
3064 checkOnlyTransferAux (fref, fexp, ffix,
3068 else if (alkind_isFresh (fkind))
3071 checkFreshTransferAux (fref, fexp, ffix,
3075 else if (alkind_isOwned (fkind))
3078 checkOwnedTransferAux (fref, fexp, ffix,
3082 else if (alkind_isDependent (fkind))
3086 (sRef_isExposed (tref) || sRef_isObserver (tref)))
3090 else if ((alkind_isOnly (tkind) || alkind_isKeep (tkind)
3091 || alkind_isOwned (tkind))
3092 || (!isfcnpass && alkind_isTemp (tkind)))
3096 if (sRef_isLocalVar (fref))
3098 sRef depRef = dependentReference (fref);
3100 if (sRef_isValid (depRef) && sRef_isLocalVar (depRef))
3103 sRef_kill (depRef, loc);
3104 sRef_kill (fref, loc);
3114 if (canLoseLocalReference (fref, loc))
3122 (FLG_DEPENDENTTRANS,
3123 message ("%s storage %q%q: %q",
3124 alkind_capName (fkind),
3125 sRef_unparseOpt (fref),
3126 transferErrorMessage (transferType, tkind),
3127 generateText (fexp, texp, tref, transferType)),
3130 DPRINTF (("Here: %s / %s",
3131 sRef_unparseFull (fref),
3132 sRef_unparseFull (tref)));
3134 sRef_showAliasInfo (fref);
3140 if (isassign && (alkind_isFresh (tkind) || alkind_isLocal (tkind)))
3144 sRef_setDependent (tref, loc);
3149 else if (alkind_isShared (fkind))
3156 if (alkind_isOnly (tkind)
3158 && (!(sRef_isObserver (tref) || sRef_isExposed (tref))
3159 && alkind_isTemp (tkind))))
3163 message ("%s storage %q%q: %q",
3164 alkind_capName (fkind),
3165 sRef_unparseOpt (fref),
3166 transferErrorMessage (transferType, tkind),
3167 generateText (fexp, texp, tref, transferType)),
3170 sRef_showAliasInfo (fref);
3175 if (alkind_isFresh (tkind) || alkind_isLocal (tkind))
3177 sRef_setShared (tref, loc);
3181 else if (alkind_isKeep (fkind))
3185 if (alkind_isKeep (tkind)
3186 || alkind_isLocal (tkind)
3187 || (isfcnreturn && sRef_isExposed (tref))
3189 && (alkind_isOnly (tkind) || alkind_isOwned (tkind))))
3191 sRef_setKept (fref, loc);
3194 && (alkind_isTemp (tkind) || alkind_isOwned (tkind)))
3200 if (!alkind_isError (tkind))
3204 message ("%s storage %q: %q",
3205 alkind_capName (fkind),
3206 transferErrorMessage (transferType, tkind),
3207 generateText (fexp, texp, tref, transferType)),
3210 sRef_showAliasInfo (fref);
3215 else if (alkind_isTemp (fkind) || alkind_isKept (fkind))
3221 if (alkind_isOnly (tkind)
3222 || alkind_isShared (tkind)
3223 || (alkind_isTemp (fkind)
3224 && !isfcnreturn && alkind_isDependent (tkind))
3225 || alkind_isOwned (tkind)
3226 || alkind_isKeep (tkind))
3228 if (!exprNode_isNullValue (fexp)
3229 && (ctype_isMutable (exprNode_getType (fexp))
3230 || (ctype_isArray (exprNode_getType (fexp))
3231 && sRef_isParam (fref)))
3232 && (!iseitherassign || sRef_isReference (tref)))
3234 if (sRef_isThroughArrayFetch (fref))
3237 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3238 FLG_STRICTUSERELEASED,
3239 message ("%s storage %q%q: %q",
3240 alkind_capName (fkind),
3241 sRef_unparseOpt (fref),
3242 transferErrorMessage (transferType, tkind),
3243 generateText (fexp, texp, tref, transferType)),
3246 sRef_showAliasInfo (fref);
3252 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3253 message ("%s storage %q%q: %q",
3254 alkind_capName (fkind),
3255 sRef_unparseOpt (fref),
3256 transferErrorMessage (transferType, tkind),
3257 generateText (fexp, texp, tref, transferType)),
3260 sRef_showAliasInfo (fref);
3266 else if (alkind_isRefCounted (fkind) || alkind_isKillRef (fkind))
3268 if (alkind_isNewRef (tkind))
3271 ** check that the refs field has been modified
3274 if (!sRef_isConst (fref))
3278 message ("Reference counted storage returned without modifying "
3279 "reference count: %s",
3280 exprNode_unparse (fexp)),
3284 else if (iseitherassign)
3286 if (alkind_isRefCounted (fkind))
3288 if (!sRef_isLocalVar (tref))
3293 ("Assignment to non-local from reference counted storage: %s",
3294 exprNode_unparse (fexp)),
3296 ("Reference counted storage should call a function returning "
3297 "a newref instead of direct assignments."),
3308 if (alkind_isRefCounted (tkind) || alkind_isTemp (tkind))
3310 /* okay --- no change in state */
3312 else if (alkind_isKillRef (tkind))
3314 if (!ffix && !tfix && !(transferType == TT_FCNRETURN))
3316 sRef_killComplete (fref, loc);
3321 if (!alkind_isError (tkind))
3325 message ("Reference counted storage %q: %q",
3326 transferErrorMessage (transferType, tkind),
3327 generateText (fexp, texp, tref, transferType)),
3340 if (alkind_isOnly (tkind) || alkind_isKeep (tkind))
3342 if (sRef_isAddress (fref))
3345 (FLG_IMMEDIATETRANS,
3346 message ("Immediate address %q %q: %q",
3347 sRef_unparse (fref),
3348 transferErrorMessage (transferType, tkind),
3349 generateText (fexp, texp, tref, transferType)),
3352 sRef_setAliasKind (fref, AK_ERROR, loc);
3356 if ((alkind_isUnknown (fkind) || alkind_isStatic (fkind))
3357 && !sRef_isDefinitelyNull (fref)
3359 && (!exprNode_isNullValue (fexp)))
3361 flagcode errkind = alkind_isStatic (fkind)
3362 ? FLG_STATICTRANS : FLG_UNKNOWNTRANS;
3364 if (transferType == TT_GLOBINIT)
3366 if (errkind == FLG_STATICTRANS)
3368 errkind = FLG_STATICINITTRANS;
3372 errkind = FLG_UNKNOWNINITTRANS;
3378 message ("%s storage %s %q: %q",
3379 alkind_capName (fkind),
3380 exprNode_unparse (fexp),
3381 transferErrorMessage (transferType, tkind),
3382 generateText (fexp, texp, tref, transferType)),
3385 sRef_showAliasInfo (fref);
3390 /* don't kill shared to suppress future messages */
3391 if (!alkind_isShared (fkind))
3397 /*< yuk! should do this in aliasaux >*/
3399 if (!sRef_isNSLocalVar (tref) && !sRef_sameName (fref, tref))
3403 sRef_setKeptComplete (fref, loc);
3407 sRef_setKept (fref, loc);
3418 if (alkind_isKeep (tkind))
3420 sRef_setKeptComplete (fref, loc);
3424 sRef_killComplete (fref, loc);
3429 if (alkind_isKeep (tkind))
3431 sRef_setKept (fref, loc);
3435 sRef_kill (fref, loc);
3442 else if (alkind_isOwned (tkind))
3444 /* don't kill shared to suppress future messages */
3445 if (!alkind_isShared (fkind))
3448 || !sRef_sameName (fref, tref)) /* result of return parameter */
3454 sRef_setDependentComplete (fref, loc);
3458 sRef_setDependent (fref, loc);
3464 else if (alkind_isShared (tkind))
3466 if (alkind_isFresh (fkind) || alkind_isLocal (fkind))
3470 sRef_setShared (fref, loc);
3474 else if (alkind_isUnknown (tkind) && context_getFlag (FLG_MEMIMPLICIT))
3476 if (alkind_isDependent (fkind))
3478 if (!exprNode_isNullValue (fexp)
3479 && ctype_isMutable (exprNode_getType (fexp))
3480 && (!iseitherassign || sRef_isReference (tref)))
3482 if (canLoseReference (fref, loc))
3489 (FLG_DEPENDENTTRANS,
3490 message ("%s storage %q%q: %q",
3491 alkind_capName (fkind),
3492 sRef_unparseOpt (fref),
3493 transferErrorMessage (transferType, tkind),
3494 generateText (fexp, texp, tref, transferType)),
3497 DPRINTF (("Here: %s / %s", sRef_unparseFull (fref),
3498 sRef_unparseFull (tref)));
3499 sRef_showAliasInfo (fref);
3505 else if (alkind_isNewRef (tkind))
3509 sRef_killComplete (fref, loc);
3512 else if (alkind_isKillRef (tkind))
3514 if (transferType == TT_FCNRETURN)
3516 if (sRef_isNewRef (fref))
3520 message ("New reference returned as temp reference: %q",
3521 generateText (fexp, texp, tref, transferType)),
3524 sRef_showAliasInfo (fref);
3530 if (sRef_isNewRef (fref))
3532 sRef_killComplete (fref, loc);
3536 if (sRef_isRefCounted (fref)
3537 && sRef_isCvar (fref)
3538 && !sRef_isLocalVar (fref))
3543 ("External reference counted storage released: %q",
3544 generateText (fexp, texp, tref, transferType)),
3547 sRef_showAliasInfo (fref);
3563 ** assigns fexp := tref or passes fexp as a parameter, or returns fexp.
3565 ** For assignments, sets alias and definition state accordingly.
3569 checkTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref,
3570 fileloc loc, transferKind transferType)
3574 if (context_inProtectVars ())
3580 ** for local references, we need to check
3581 ** the transfer for all possible aliases.
3584 if (sRef_isLocalVar (tref) && transferType != TT_DOASSIGN)
3586 sRefSet alias = usymtab_allAliases (tref);
3588 sRefSet_realElements (alias, atref)
3590 sRef abase = sRef_getRootBase (atref);
3592 if (sRef_isKnown (atref)
3593 && !sRef_isLocalVar (abase)
3594 && !sRef_isExternal (abase))
3596 atref = sRef_updateSref (atref);
3598 if (sRef_hasName (atref))
3600 if (!sRef_isNew (atref)
3601 && !sRef_sameName (tref, atref))
3603 context_setAliasAnnote (atref, tref);
3606 checkTransferAux (fexp, fref, TRUE,
3610 context_clearAliasAnnote ();
3613 } end_sRefSet_realElements;
3615 sRefSet_free (alias);
3619 if (sRef_isLocalVar (fref))
3621 sRefSet alias = usymtab_allAliases (fref);
3623 sRefSet_realElements (alias, afref)
3625 sRef abase = sRef_getRootBase (afref);
3627 if (sRef_isKnown (afref)
3628 && !sRef_isLocalVar (abase)
3629 && !sRef_isExternal (abase))
3631 afref = sRef_updateSref (afref);
3633 if (sRef_hasName (afref))
3635 if (!sRef_isNew (afref)
3636 && !sRef_sameName (afref, fref))
3638 context_setAliasAnnote (afref, fref);
3641 checkTransferAux (fexp, afref, FALSE,
3645 context_clearAliasAnnote ();
3648 } end_sRefSet_realElements;
3650 sRefSet_free (alias);
3655 checkTransferAux (fexp, fref, FALSE, texp, tref, FALSE,
3661 static /*@exposed@*/ sRef
3662 dependentReference (sRef sr)
3664 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
3667 ** If there is a local variable that aliases sr, then there is no
3668 ** error. Make the local an only.
3671 if (!sRefSet_isEmpty (ab))
3673 sRef res = sRef_undefined;
3676 ** make one an only, others alias it
3680 sRefSet_realElements (ab, current)
3682 if (sRef_isOwned (current))
3687 } end_sRefSet_realElements;
3693 return sRef_undefined;
3696 bool canLoseReference (sRef sr, fileloc loc)
3698 bool gotone = FALSE;
3699 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
3703 ** if there is a local variable that aliases sr, then there is no
3704 ** error. Make the local an only.
3707 if (!sRefSet_isEmpty (ab))
3710 ** make one an only, others alias it
3714 sRefSet_realElements (ab, current)
3716 sRef_setLastReference (current, sr, loc);
3719 } end_sRefSet_realElements;
3727 bool canLoseLocalReference (sRef sr, fileloc loc)
3729 bool gotone = FALSE;
3730 sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
3734 ** if there is a local variable that aliases sr, then there is no
3735 ** error. Make the local an only.
3738 if (!sRefSet_isEmpty (ab))
3741 ** make one an only, others alias it
3745 sRefSet_realElements (ab, current)
3747 if (sRef_isRealLocalVar (sRef_getRootBase (current)))
3749 sRef_setLastReference (current, sr, loc);
3753 } end_sRefSet_realElements;
3762 /*start modification */
3764 /*added by David Larochelle 4/13/2000*/
3766 /*this is modeled after checkTransferNullAux */
3769 checkTransferNullTerminatedAux (sRef fref, exprNode fexp,
3770 /*@unused@*/ bool ffix,
3771 sRef tref, exprNode texp, /*@unused@*/ bool tfix,
3772 fileloc loc, transferKind transferType)
3774 alkind tkind = sRef_getAliasKind (tref);
3775 ctype ttyp = ctype_realType (sRef_getType (tref));
3778 printf ("checking for fexp-%s\n", exprNode_unparse(fexp));
3779 printf ("checking for texp-%s\n", exprNode_unparse(texp));
3782 if (ctype_isUnknown (ttyp))
3784 ttyp = exprNode_getType (texp);
3786 if (ctype_isUnknown (ttyp))
3788 ttyp = exprNode_getType (fexp);
3790 if (ctype_isUnknown (ttyp))
3792 ttyp = sRef_getType (fref);
3797 if (ctype_isFunction (ttyp) && (transferType == TT_FCNRETURN))
3799 ttyp = ctype_returnValue (ttyp);
3803 ** check for null terminated (don't need to check aliases??)
3806 if (!sRef_isNullTerminated (fref)
3807 && !usymtab_isGuarded (fref)
3808 && ctype_isRealAP (ttyp))
3810 if (!alkind_isLocal (tkind) && !alkind_isFresh (tkind)
3811 //this should be perhapsNullTerminated but I didn't want to write
3812 && (sRef_isPossiblyNullTerminated (tref) ||
3813 sRef_isNullTerminated (tref))
3814 && !(transferType == TT_DOASSIGN))
3816 if (transferType == TT_GLOBINIT)
3818 printf("-----------------------------------NULLTERMINATED ERROR1\n");
3819 if (sRef_isPossiblyNullTerminated (fref)) {
3821 (FLG_NULLTERMINATEDWARNING,
3822 message ("%s %q initialized to %s value: %q",
3823 sRef_getScopeName (tref),
3824 sRef_unparse (tref),
3825 sRef_ntMessage (fref),
3826 generateText (fexp, texp, tref, transferType)),
3830 printf ("NULLTERMINATED REFERENCE ERROR\n");
3831 // printf ("First way\n");
3837 (FLG_NULLTERMINATED,
3838 message ("%s %q initialized to %s value: %q",
3839 sRef_getScopeName (tref),
3840 sRef_unparse (tref),
3841 sRef_ntMessage (fref),
3842 generateText (fexp, texp, tref, transferType)),
3846 printf ("NULLTERMINATED REFERENCE ERROR\n");
3847 // printf ("First way\n");
3850 printf("-----------------------------\n\n");
3856 printf("****************************NULLTERMINATED ERROR2\n");
3857 // ((transferType == TT_FCNPASS) ? FLG_NULLPASS : FLG_NULLRET,
3859 if (sRef_isPossiblyNullTerminated (fref))
3862 (FLG_NULLTERMINATEDWARNING,
3863 message ("%q storage %q%s: %q",
3864 cstring_capitalize (sRef_ntMessage (fref)),
3865 sRef_unparseOpt (fref),
3866 transferNTMessage (transferType),
3867 generateText (fexp, texp, tref, transferType)),
3871 printf ("NULLTERMINATED REFERENCE ERROR\n");
3872 // printf ("First way\n");
3877 ((transferType == TT_FCNPASS) ? FLG_NULLTERMINATED: FLG_NULLTERMINATED,
3878 message ("%q storage %q%s: %q",
3879 cstring_capitalize (sRef_ntMessage (fref)),
3880 sRef_unparseOpt (fref),
3881 transferNTMessage (transferType),
3882 generateText (fexp, texp, tref, transferType)),
3885 // sRef_showNullInfo (fref);
3886 // sRef_setNullError (fref);
3887 printf ("SYMBOL REFERENCED IS NOT NULLTERMINATED!\n");
3890 printf("*******************************=\n\n");
3900 /* end modification */