00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 # include "lclintMacros.nf"
00029 # include "basic.h"
00030 # include "aliasChecks.h"
00031
00032 static void checkStructTransfer (exprNode p_lhs, sRef p_slhs, exprNode p_rhs, sRef p_srhs,
00033 fileloc p_loc, transferKind p_tt);
00034 static void checkLeaveTrans (uentry p_actual, transferKind p_transferType);
00035 static void checkTransfer (exprNode p_fexp, sRef p_fref,
00036 exprNode p_texp, sRef p_tref,
00037 fileloc p_loc, transferKind p_transferType);
00038 static void checkGlobTrans (uentry p_glob, transferKind p_type);
00039
00040 static ynm
00041 checkCompletelyDefined (exprNode p_fexp, sRef p_fref,
00042 exprNode p_texp, sRef p_tref,
00043 bool p_topLevel, bool p_inUnion, bool p_directUnion,
00044 fileloc p_loc, transferKind p_transferType, int p_depth,
00045 bool p_report);
00046
00047 static sRef dependentReference (sRef p_sr);
00048 static bool canLoseLocalReference (sRef p_sr, fileloc p_loc) ;
00049
00050
00051
00052
00053
00054 alkind alkind_resolve (alkind a1, alkind a2)
00055 {
00056 if (a1 == AK_UNKNOWN || a1 == AK_ERROR) return a2;
00057 if (a2 == AK_UNKNOWN || a2 == AK_ERROR || a2 == AK_LOCAL) return a1;
00058 if (a1 == AK_LOCAL) return a2;
00059 return a1;
00060 }
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 static cstring
00073 transferErrorMessage (transferKind transferType, alkind tkind)
00074 {
00075 switch (transferType)
00076 {
00077 case TT_FCNRETURN:
00078 return (message ("returned as %s", alkind_unparse (tkind)));
00079 case TT_DOASSIGN:
00080 return (message ("assigned to %s", alkind_unparse (tkind)));
00081 case TT_FIELDASSIGN:
00082 return (message ("assigned to %s", alkind_unparse (tkind)));
00083 case TT_GLOBINIT:
00084 return (message ("used as initial value for %s",
00085 alkind_unparse (tkind)));
00086 case TT_FCNPASS:
00087 return (message ("passed as %s param", alkind_unparse (tkind)));
00088 BADDEFAULT;
00089 }
00090 BADEXIT;
00091 }
00092
00093 static cstring
00094 transferErrorExpMessage (transferKind transferType, exkind tkind)
00095 {
00096 if (exkind_isUnknown (tkind))
00097 {
00098 switch (transferType)
00099 {
00100 case TT_FCNRETURN:
00101 return (cstring_makeLiteral ("returned without qualification"));
00102 case TT_FIELDASSIGN:
00103 case TT_DOASSIGN:
00104 return (cstring_makeLiteral ("assigned to unqualified reference"));
00105 case TT_FCNPASS:
00106 return (cstring_makeLiteral ("passed without qualification"));
00107 case TT_GLOBINIT:
00108 return (cstring_makeLiteral ("used as initial value for unqualified storage"));
00109 BADDEFAULT;
00110 }
00111 }
00112 else
00113 {
00114 switch (transferType)
00115 {
00116 case TT_FCNRETURN:
00117 return (message ("returned as %s", exkind_unparse (tkind)));
00118 case TT_FIELDASSIGN:
00119 case TT_DOASSIGN:
00120 return (message ("assigned to %s", exkind_unparse (tkind)));
00121 case TT_FCNPASS:
00122 return (message ("passed as %s param", exkind_unparse (tkind)));
00123 BADDEFAULT;
00124 }
00125 }
00126
00127 BADEXIT;
00128 }
00129
00130 static cstring
00131 transferNullMessage (transferKind transferType)
00132 {
00133 switch (transferType)
00134 {
00135 case TT_FCNRETURN:
00136 return (cstring_makeLiteralTemp ("returned as non-null"));
00137 case TT_DOASSIGN:
00138 case TT_FIELDASSIGN:
00139 return (cstring_makeLiteralTemp ("assigned to non-null"));
00140 case TT_GLOBINIT:
00141 return (cstring_makeLiteralTemp ("initialized to non-null"));
00142 case TT_FCNPASS:
00143 return (cstring_makeLiteralTemp ("passed as non-null param"));
00144 BADDEFAULT;
00145 }
00146 BADEXIT;
00147 }
00148
00149 static exprNode atFunction = exprNode_undefined;
00150 static int atArgNo = 0;
00151 static int atNumArgs = 0;
00152
00153 static cstring generateText (exprNode e1, exprNode e2,
00154 sRef tref, transferKind tt)
00155
00156 {
00157 if (tt == TT_DOASSIGN || tt == TT_GLOBINIT)
00158 {
00159 return (message ("%s = %s", exprNode_unparse (e2),
00160 exprNode_unparse (e1)));
00161 }
00162 else if (tt == TT_FIELDASSIGN)
00163 {
00164 return (message ("%s = %s (field %q)",
00165 exprNode_unparse (e2),
00166 exprNode_unparse (e1),
00167 sRef_unparse (tref)));
00168 }
00169 else if (tt == TT_FCNPASS)
00170 {
00171 return (message ("%s (%s%s%s)",
00172 exprNode_unparse (atFunction),
00173 (atArgNo == 1 ? cstring_undefined
00174 : cstring_makeLiteralTemp ("..., ")),
00175 exprNode_unparse (e1),
00176 (atArgNo == atNumArgs ? cstring_undefined
00177 : cstring_makeLiteralTemp (", ..."))));
00178 }
00179 else
00180 {
00181 return (cstring_copy (exprNode_unparse (e1)));
00182 }
00183 }
00184
00185 static cstring
00186 transferType_unparse (transferKind transferType)
00187 {
00188 switch (transferType)
00189 {
00190 case TT_FCNRETURN:
00191 return (cstring_makeLiteralTemp ("Returned"));
00192 case TT_DOASSIGN:
00193 case TT_FIELDASSIGN:
00194 return (cstring_makeLiteralTemp ("Assigned"));
00195 case TT_FCNPASS:
00196 return (cstring_makeLiteralTemp ("Passed"));
00197 case TT_GLOBINIT:
00198 return (cstring_makeLiteralTemp ("Initialized"));
00199 case TT_GLOBRETURN:
00200 return (cstring_makeLiteralTemp ("GLOB RETURN!"));
00201 case TT_GLOBPASS:
00202 return (cstring_makeLiteralTemp ("GLOB PASS!"));
00203 case TT_PARAMRETURN:
00204 return (cstring_makeLiteralTemp ("PARAM RETURN!"));
00205 case TT_LEAVETRANS:
00206 return (cstring_makeLiteralTemp ("LEAVE TRANS!"));
00207 BADDEFAULT;
00208 }
00209 BADEXIT;
00210 }
00211
00212 static cstring udError (sRef s)
00213 {
00214 if (sRef_isDead (s))
00215 {
00216 return cstring_makeLiteralTemp ("released");
00217 }
00218 else if (sRef_isAllocated (s))
00219 {
00220 return cstring_makeLiteralTemp ("allocated but not defined");
00221 }
00222 else
00223 {
00224 return cstring_makeLiteralTemp ("undefined");
00225 }
00226 }
00227
00228 static
00229 cstring defExpl (sRef s)
00230 {
00231 sRef rb = sRef_getRootBase (s);
00232
00233 if (sRef_sameName (rb, s))
00234 {
00235 if (sRef_isAllocated (s))
00236 {
00237 return cstring_makeLiteral (" (allocated only)");
00238 }
00239 return cstring_undefined;
00240 }
00241 else
00242 {
00243 return (message (" (%q is %s)", sRef_unparse (s), udError (s)));
00244 }
00245 }
00246
00247
00248
00249
00250
00251
00252 static ynm
00253 checkCompletelyDefined (exprNode fexp, sRef fref,
00254 exprNode texp, sRef tref,
00255 bool topLevel, bool inUnion, bool directUnion,
00256 fileloc loc, transferKind transferType,
00257 int depth, bool report)
00258 {
00259 ctype ct;
00260 alkind fkind = sRef_getAliasKind (fref);
00261 alkind tkind = sRef_getAliasKind (tref);
00262
00263 if (depth > MAXDEPTH)
00264 {
00265 llquietbug
00266 (message
00267 ("Check definition limit exceeded, checking %q. "
00268 "This either means there is a variable with at least "
00269 "%d indirections apparent in the program text, or "
00270 "there is a bug in LCLint.",
00271 sRef_unparse (fref),
00272 MAXDEPTH));
00273
00274 return YES;
00275 }
00276
00277 if (!sRef_isKnown (fref))
00278 {
00279 return YES;
00280 }
00281
00282 if (alkind_isStack (fkind))
00283 {
00284 ctype rt = ctype_realType (sRef_getType (tref));
00285
00286 if (ctype_isMutable (rt) && !ctype_isSU (rt))
00287 {
00288 if (transferType == TT_PARAMRETURN)
00289 {
00290 if (optgenerror
00291 (FLG_RETSTACK,
00292 message
00293 ("Stack-allocated storage %qreachable from parameter %q",
00294 sRef_unparseOpt (fref),
00295 sRef_unparse (sRef_getRootBase (fref))),
00296 loc))
00297 {
00298 sRef_showAliasInfo (fref);
00299 }
00300 }
00301 else if (transferType == TT_GLOBRETURN)
00302 {
00303 if (optgenerror
00304 (FLG_RETSTACK,
00305 message
00306 ("Stack-allocated storage %qreachable from global %q",
00307 sRef_unparseOpt (fref),
00308 sRef_unparse (sRef_getRootBase (fref))),
00309 loc))
00310 {
00311 sRef_showAliasInfo (fref);
00312 }
00313 }
00314 else if (transferType == TT_FCNRETURN)
00315 {
00316 if (optgenerror
00317 (FLG_RETSTACK,
00318 message
00319 ("Stack-allocated storage %qreachable from return value: %s",
00320 sRef_unparseOpt (fref),
00321 exprNode_unparse (fexp)),
00322 loc))
00323 {
00324 sRef_showAliasInfo (fref);
00325 }
00326 }
00327 else
00328 {
00329
00330 }
00331 }
00332 }
00333
00334 if (!topLevel)
00335 {
00336 if ((sRef_isObserver (fref) && !sRef_isObserver (tref))
00337 || (sRef_isExposed (fref) && !(sRef_isObserver (tref)
00338 || sRef_isExposed (tref))))
00339 {
00340 flagcode code = (sRef_isObserver (fref)
00341 ? FLG_OBSERVERTRANS : FLG_EXPOSETRANS);
00342
00343 if (!sRef_isStateLive (fref))
00344 {
00345 ;
00346 }
00347 else if (transferType == TT_DOASSIGN
00348 || transferType == TT_FIELDASSIGN
00349 || transferType == TT_GLOBINIT
00350 || transferType == TT_FCNPASS)
00351 {
00352 ;
00353 }
00354 else if (transferType == TT_PARAMRETURN)
00355 {
00356 if (optgenerror
00357 (code,
00358 message
00359 ("%s storage %qreachable from %s parameter",
00360 exkind_capName (sRef_getExKind (fref)),
00361 sRef_unparseOpt (fref),
00362 exkind_unparseError (sRef_getExKind (tref))),
00363 loc))
00364 {
00365 sRef_showExpInfo (fref);
00366 sRef_setExKind (fref, XO_UNKNOWN, loc);
00367 }
00368 }
00369 else if (transferType == TT_LEAVETRANS)
00370 {
00371 ;
00372 }
00373 else if (transferType == TT_GLOBINIT)
00374 {
00375 if (optgenerror
00376 (code,
00377 message
00378 ("%s storage %qreachable from %s initial value",
00379 exkind_capName (sRef_getExKind (fref)),
00380 sRef_unparseOpt (fref),
00381 exkind_unparseError (sRef_getExKind (tref))),
00382 loc))
00383 {
00384 sRef_showExpInfo (fref);
00385 sRef_setExKind (fref, XO_UNKNOWN, loc);
00386 }
00387 }
00388 else if (transferType == TT_GLOBRETURN)
00389 {
00390 if (optgenerror
00391 (code,
00392 message
00393 ("%s storage %qreachable from %s global",
00394 exkind_capName (sRef_getExKind (fref)),
00395 sRef_unparseOpt (fref),
00396 exkind_unparseError (sRef_getExKind (tref))),
00397 loc))
00398 {
00399 sRef_showExpInfo (fref);
00400 sRef_setExKind (fref, XO_UNKNOWN, loc);
00401 }
00402 }
00403 else if (transferType == TT_FCNRETURN)
00404 {
00405 if (optgenerror
00406 (code,
00407 message
00408 ("%s storage %qreachable from %s return value",
00409 exkind_capName (sRef_getExKind (fref)),
00410 sRef_unparseOpt (fref),
00411 exkind_unparseError (sRef_getExKind (tref))),
00412 loc))
00413 {
00414 sRef_showExpInfo (fref);
00415 sRef_setExKind (fref, XO_UNKNOWN, loc);
00416 }
00417 }
00418 else
00419 {
00420 llcontbug (message ("Transfer type: %s",
00421 transferType_unparse (transferType)));
00422
00423 if (optgenerror
00424 (code,
00425 message
00426 ("%s storage %qreachable from %s return value",
00427 exkind_capName (sRef_getExKind (fref)),
00428 sRef_unparseOpt (fref),
00429 exkind_unparseError (sRef_getExKind (tref))),
00430 loc))
00431 {
00432 sRef_showExpInfo (fref);
00433 sRef_setExKind (fref, XO_UNKNOWN, loc);
00434 }
00435 }
00436
00437 }
00438
00439 if (!alkind_compatible (fkind, tkind))
00440 {
00441 if (fkind == AK_UNKNOWN && !sRef_isStateLive (fref))
00442 {
00443 ;
00444 }
00445 else if (transferType == TT_DOASSIGN)
00446 {
00447 ;
00448 }
00449 else if (transferType == TT_FCNPASS)
00450 {
00451 if (alkind_isKnown (sRef_getAliasKind (tref)))
00452 {
00453 if (optgenerror
00454 (FLG_COMPMEMPASS,
00455 message
00456 ("Storage %qreachable from passed parameter "
00457 "is %s (should be %s): %s",
00458 sRef_unparseOpt (fref),
00459 alkind_unparse (sRef_getAliasKind (fref)),
00460 alkind_unparse (sRef_getAliasKind (tref)),
00461 exprNode_unparse (fexp)),
00462 loc))
00463 {
00464 sRef_showAliasInfo (fref);
00465 }
00466 }
00467 }
00468 else if (transferType == TT_PARAMRETURN)
00469 {
00470 bool noerror = FALSE;
00471
00472 if (alkind_isDependent (sRef_getAliasKind (fref)))
00473 {
00474 if (canLoseLocalReference (fref, loc))
00475 {
00476 noerror = TRUE;
00477 }
00478 }
00479
00480 if (!noerror
00481 && optgenerror
00482 (FLG_COMPMEMPASS,
00483 message
00484 ("Storage %qreachable from parameter is %s (should be %s)",
00485 sRef_unparseOpt (fref),
00486 alkind_unparse (sRef_getAliasKind (fref)),
00487 alkind_unparse (sRef_getAliasKind (tref))),
00488 loc))
00489 {
00490 sRef_showAliasInfo (fref);
00491 }
00492 }
00493 else if (transferType == TT_LEAVETRANS)
00494 {
00495 if (optgenerror
00496 (FLG_COMPMEMPASS,
00497 message
00498 ("Storage %qreachable from temporary reference is %s "
00499 "at scope exit (should be %s)",
00500 sRef_unparseOpt (fref),
00501 alkind_unparse (sRef_getAliasKind (fref)),
00502 alkind_unparse (sRef_getAliasKind (tref))),
00503 loc))
00504 {
00505 sRef_showAliasInfo (fref);
00506 }
00507 }
00508 else if (transferType == TT_GLOBRETURN)
00509 {
00510 if (optgenerror
00511 (FLG_COMPMEMPASS,
00512 message
00513 ("Storage %qreachable from global is %s (should be %s)",
00514 sRef_unparseOpt (fref),
00515 alkind_unparse (sRef_getAliasKind (fref)),
00516 alkind_unparse (sRef_getAliasKind (tref))),
00517 loc))
00518 {
00519 sRef_showAliasInfo (fref);
00520 }
00521 }
00522 else if (transferType == TT_FCNRETURN)
00523 {
00524 if (optgenerror
00525 (FLG_COMPMEMPASS,
00526 message
00527 ("Storage %qreachable from return value is %s (should be %s)",
00528 sRef_unparseOpt (fref),
00529 alkind_unparse (sRef_getAliasKind (fref)),
00530 alkind_unparse (sRef_getAliasKind (tref))),
00531 loc))
00532 {
00533 sRef_showAliasInfo (fref);
00534 }
00535 }
00536 else if (transferType == TT_GLOBINIT)
00537 {
00538 if (optgenerror
00539 (FLG_COMPMEMPASS,
00540 message
00541 ("Storage %qreachable from initial value is %s (should be %s)",
00542 sRef_unparseOpt (fref),
00543 alkind_unparse (sRef_getAliasKind (fref)),
00544 alkind_unparse (sRef_getAliasKind (tref))),
00545 loc))
00546 {
00547 sRef_showAliasInfo (fref);
00548 }
00549 }
00550 else
00551 {
00552 llcontbug (message ("Transfer type: %s",
00553 transferType_unparse (transferType)));
00554
00555 if (optgenerror
00556 (FLG_COMPMEMPASS,
00557 message
00558 ("Storage %qreachable from return value is %s (should be %s)",
00559 sRef_unparseOpt (fref),
00560 alkind_unparse (sRef_getAliasKind (fref)),
00561 alkind_unparse (sRef_getAliasKind (tref))),
00562 loc))
00563 {
00564 sRef_showAliasInfo (fref);
00565 }
00566 }
00567 }
00568
00569 if (sRef_isDead (fref))
00570 {
00571 if (directUnion)
00572 {
00573 return NO;
00574 }
00575
00576 if (transferType == TT_PARAMRETURN)
00577 {
00578 if (optgenerror
00579 (FLG_USERELEASED,
00580 message
00581 ("Released storage %q reachable from parameter at return point",
00582 sRef_unparse (fref)),
00583 loc))
00584 {
00585 sRef_showStateInfo (fref);
00586 return YES;
00587 }
00588 }
00589 else if (transferType == TT_LEAVETRANS)
00590 {
00591 if (optgenerror
00592 (FLG_USERELEASED,
00593 message ("Released storage %q reachable from temporary "
00594 "reference at scope exit",
00595 sRef_unparse (fref)),
00596 loc))
00597 {
00598 sRef_showStateInfo (fref);
00599 return YES;
00600 }
00601 }
00602 else if (transferType == TT_GLOBRETURN)
00603 {
00604 if (optgenerror
00605 (FLG_GLOBSTATE,
00606 message ("Released storage %q reachable from global",
00607 sRef_unparse (fref)),
00608 loc))
00609 {
00610 sRef_showStateInfo (fref);
00611 return YES;
00612 }
00613 }
00614 else if (transferType == TT_FCNPASS)
00615 {
00616 if (optgenerror
00617 (FLG_USERELEASED,
00618 message ("Released storage %q reachable from passed parameter",
00619 sRef_unparse (fref)),
00620 loc))
00621 {
00622 sRef_showStateInfo (fref);
00623 return YES;
00624 }
00625 }
00626 else
00627 {
00628 if (optgenerror
00629 (FLG_USERELEASED,
00630 message ("Released storage %q reachable from parameter",
00631 sRef_unparse (fref)),
00632 loc))
00633 {
00634 sRef_showStateInfo (fref);
00635 return YES;
00636 }
00637 }
00638 }
00639 }
00640
00641 if (!topLevel
00642 && sRef_possiblyNull (fref)
00643 && !sRef_perhapsNull (tref)
00644 && ctype_isRealPointer (sRef_getType (tref))
00645 && !usymtab_isGuarded (fref))
00646 {
00647 if (transferType == TT_FCNRETURN)
00648 {
00649 if (optgenerror
00650 (FLG_NULLRET,
00651 message ("%q storage %qderivable from return value: %s",
00652 cstring_capitalize (sRef_nullMessage (fref)),
00653 sRef_unparseOpt (fref),
00654 exprNode_unparse (fexp)),
00655 loc))
00656 {
00657 sRef_showNullInfo (fref);
00658 sRef_setNullError (fref);
00659 }
00660 }
00661 else if (transferType == TT_GLOBRETURN || transferType == TT_PARAMRETURN)
00662 {
00663 if (optgenerror
00664 (FLG_NULLSTATE,
00665 message
00666 ("Function returns with %s storage derivable from %q %q",
00667 sRef_nullMessage (fref),
00668 cstring_makeLiteral ((transferType == TT_GLOBRETURN)
00669 ? "global" : "parameter"),
00670 sRef_unparse (fref)),
00671 loc))
00672 {
00673 sRef_showNullInfo (fref);
00674 sRef_setNullError (fref);
00675 }
00676 }
00677 else if (transferType == TT_GLOBPASS)
00678 {
00679 if (optgenerror
00680 (FLG_NULLPASS,
00681 message ("Function called with %s storage "
00682 "derivable from global %q",
00683 sRef_nullMessage (fref),
00684 sRef_unparse (fref)),
00685 loc))
00686 {
00687 sRef_showNullInfo (fref);
00688 sRef_setNullError (fref);
00689 }
00690 }
00691 else if (transferType == TT_FCNPASS)
00692 {
00693 if (optgenerror
00694 (FLG_NULLSTATE,
00695 message ("%q storage %qderivable from parameter %q",
00696 cstring_capitalize (sRef_nullMessage (fref)),
00697 sRef_unparseOpt (fref),
00698 generateText (fexp, exprNode_undefined,
00699 sRef_undefined, TT_FCNPASS)),
00700 loc))
00701 {
00702 sRef_showNullInfo (fref);
00703 sRef_setNullError (fref);
00704 }
00705 }
00706 else
00707 {
00708 llassert (transferType == TT_DOASSIGN
00709 || transferType == TT_GLOBINIT
00710 || transferType == TT_LEAVETRANS);
00711 }
00712 }
00713
00714 if (sRef_isRelDef (tref)
00715 || sRef_isPartial (tref)
00716 || sRef_isAllocated (tref)
00717 || sRef_isStateSpecial (tref))
00718 {
00719
00720 return YES;
00721 }
00722
00723 ct = ctype_realType (sRef_getType (fref));
00724
00725 if (!(sRef_isAnyDefined (fref)
00726 || sRef_isPdefined (fref)
00727 || sRef_isAllocated (fref)
00728 || sRef_isStateUnknown (fref)))
00729 {
00730 if (transferType == TT_GLOBRETURN)
00731 {
00732 if (report
00733 && optgenerror
00734 (FLG_COMPDEF,
00735 message ("Function returns with global %q not "
00736 "completely defined%q",
00737 sRef_unparse (sRef_getRootBase (fref)),
00738 defExpl (fref)),
00739 loc))
00740 {
00741 sRef_showStateInfo (fref);
00742 sRef_setDefined (fref, loc);
00743 }
00744 }
00745 else if (transferType == TT_GLOBPASS)
00746 {
00747 if (report &&
00748 optgenerror
00749 (FLG_COMPDEF,
00750 message
00751 ("Function called with global %q not completely defined%q",
00752 sRef_unparse (sRef_getRootBase (fref)),
00753 defExpl (fref)),
00754 loc))
00755 {
00756 sRef_showStateInfo (fref);
00757 sRef_setDefined (fref, loc);
00758 }
00759 }
00760 else if (transferType == TT_PARAMRETURN)
00761 {
00762 if (report && !topLevel
00763 && optgenerror
00764 (FLG_COMPDEF,
00765 message ("Function returns storage %q reachable from parameter not "
00766 "completely defined%q",
00767 sRef_unparse (sRef_getRootBase (fref)),
00768 defExpl (fref)),
00769 loc))
00770 {
00771 sRef_showStateInfo (fref);
00772 sRef_setDefined (fref, loc);
00773 }
00774 }
00775 else if (transferType == TT_LEAVETRANS)
00776 {
00777 if (report && !topLevel
00778 && optgenerror
00779 (FLG_COMPDEF,
00780 message ("Scope exits with storage %q reachable from "
00781 "temporary reference not completely defined%q",
00782 sRef_unparse (sRef_getRootBase (fref)),
00783 defExpl (fref)),
00784 loc))
00785 {
00786 sRef_showStateInfo (fref);
00787 sRef_setDefined (fref, loc);
00788 }
00789 }
00790 else
00791 {
00792 if (transferType != TT_DOASSIGN
00793 && (!(sRef_isNew (fref) || sRef_isType (fref))))
00794 {
00795 if (report)
00796 {
00797 if (sRef_isDead (fref))
00798 {
00799 if (optgenerror
00800 (FLG_USERELEASED,
00801 message ("%s storage %qwas released: %q",
00802 transferType_unparse (transferType),
00803 sRef_unparseOpt (fref),
00804 generateText (fexp, texp, tref, transferType)),
00805 loc))
00806 {
00807 sRef_showStateInfo (fref);
00808 }
00809 }
00810 else
00811 {
00812 if (optgenerror
00813 (FLG_COMPDEF,
00814 message
00815 ("%s storage %qnot completely defined%q: %q",
00816 transferType_unparse (transferType),
00817 sRef_unparseOpt (sRef_getRootBase (fref)),
00818 defExpl (fref),
00819 generateText (fexp, texp, tref, transferType)),
00820 loc))
00821 {
00822 sRef rb = sRef_getRootBase (fref);
00823 sRef_showStateInfo (fref);
00824 sRef_setDefinedComplete (rb, loc);
00825 }
00826 }
00827 }
00828 }
00829 else
00830 {
00831
00832 if (sRef_isAllocated (fref) && sRef_isValid (tref)
00833 && (transferType == TT_DOASSIGN))
00834 {
00835 sRef_setAllocatedComplete (tref, loc);
00836 }
00837 return YES;
00838 }
00839 }
00840
00841 return NO;
00842 }
00843
00844 if (ctype_isUnknown (ct))
00845 {
00846 return YES;
00847 }
00848 else if (ctype_isPointer (ct))
00849 {
00850 ctype tct = ctype_realType (sRef_getType (tref));
00851
00852 if (sRef_isStateUnknown (fref))
00853 {
00854 return NO;
00855 }
00856 else
00857 {
00858 if (ctype_isAP (tct) || ctype_isUnknown (tct))
00859 {
00860 sRef fptr = sRef_constructDeref (fref);
00861 sRef tptr = sRef_constructDeref (tref);
00862
00863 return (checkCompletelyDefined (fexp, fptr, texp, tptr,
00864 FALSE, inUnion, FALSE, loc,
00865 transferType, depth + 1, report));
00866 }
00867 else
00868 {
00869 return YES;
00870 }
00871 }
00872 }
00873 else if (ctype_isArray (ct))
00874 {
00875 return YES;
00876 }
00877 else if (ctype_isStruct (ct))
00878 {
00879 ctype tct = ctype_realType (sRef_getType (tref));
00880
00881 if (ctype_match (ct, tct))
00882 {
00883 bool isOk = TRUE;
00884 bool hasOneDefined = FALSE;
00885 cstringSList badFields = cstringSList_undefined;
00886
00887 if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref))
00888 {
00889 return YES;
00890 }
00891
00892 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
00893 {
00894 sRefSet_realElements (sRef_derivedFields (fref), sr)
00895 {
00896 bool thisField;
00897
00898 hasOneDefined = TRUE;
00899
00900 if (sRef_isField (sr))
00901 {
00902 cstring fieldname = sRef_getField (sr);
00903 sRef fldref = sRef_makeField (tref, fieldname);
00904 bool shouldCheck = !sRef_isRecursiveField (fldref);
00905
00906 if (shouldCheck)
00907 {
00908 thisField =
00909 ynm_toBoolRelaxed
00910 (checkCompletelyDefined (fexp, sr, texp, fldref,
00911 FALSE, inUnion, FALSE, loc,
00912 transferType, depth + 1,
00913 FALSE));
00914 }
00915 else
00916 {
00917 thisField = TRUE;
00918 }
00919
00920 if (!thisField)
00921 {
00922 isOk = FALSE;
00923 badFields = cstringSList_add (badFields,
00924 sRef_getField (sr));
00925 }
00926 }
00927 } end_sRefSet_realElements;
00928 }
00929 else if (sRef_isAllocated (fref))
00930 {
00931
00932
00933
00934
00935 uentryList fields = ctype_getFields (ct);
00936
00937 uentryList_elements (fields, ue)
00938 {
00939 bool thisField;
00940 cstring name = uentry_getRealName (ue);
00941 sRef ffield = sRef_makeField (fref, name);
00942 sRef tfield = sRef_makeField (tref, name);
00943 bool shouldCheck = !sRef_isRecursiveField (tfield);
00944
00945 if (!shouldCheck)
00946 {
00947 thisField = TRUE;
00948 }
00949 else
00950 {
00951 thisField = ynm_toBoolRelaxed
00952 (checkCompletelyDefined (fexp, ffield, texp, tfield,
00953 FALSE, inUnion, FALSE,
00954 loc, transferType,
00955 depth + 1, FALSE));
00956 }
00957
00958 if (!thisField)
00959 {
00960 isOk = FALSE;
00961 badFields = cstringSList_add (badFields, uentry_rawName (ue));
00962 }
00963 else
00964 {
00965 hasOneDefined = TRUE;
00966 }
00967 } end_uentryList_elements;
00968 }
00969 else
00970 {
00971 ;
00972 }
00973
00974 if (!isOk && (!inUnion || hasOneDefined))
00975 {
00976 if (transferType == TT_GLOBRETURN)
00977 {
00978 if (optgenerror
00979 (FLG_COMPDEF,
00980 message ("Global storage %q contains %d undefined field%p "
00981 "when call returns: %q",
00982 sRef_unparse (fref),
00983 cstringSList_size (badFields),
00984 cstringSList_unparseAbbrev (badFields)),
00985 loc))
00986 {
00987 sRef_setDefined (fref, loc);
00988 }
00989 }
00990 else if (transferType == TT_GLOBPASS)
00991 {
00992 if (optgenerror
00993 (FLG_COMPDEF,
00994 message ("Global storage %q contains %d undefined field%p "
00995 "before call: %q",
00996 sRef_unparse (fref),
00997 cstringSList_size (badFields),
00998 cstringSList_unparseAbbrev (badFields)),
00999 loc))
01000 {
01001 sRef_setDefined (fref, loc);
01002 }
01003 }
01004 else if (transferType == TT_PARAMRETURN)
01005 {
01006 if (optgenerror
01007 (FLG_COMPDEF,
01008 message ("Storage %qreachable from parameter "
01009 "contains %d undefined field%p: %q",
01010 sRef_unparseOpt (fref),
01011 cstringSList_size (badFields),
01012 cstringSList_unparseAbbrev (badFields)),
01013 loc))
01014 {
01015 sRef_setDefined (fref, loc);
01016 }
01017 }
01018 else if (transferType == TT_LEAVETRANS)
01019 {
01020
01021 }
01022 else
01023 {
01024 if (optgenerror
01025 (FLG_COMPDEF,
01026 message ("%s storage %qcontains %d undefined field%p: %q",
01027 transferType_unparse (transferType),
01028 sRef_unparseOpt (fref),
01029 cstringSList_size (badFields),
01030 cstringSList_unparseAbbrev (badFields)),
01031 loc))
01032 {
01033 sRef_setDefined (fref, loc);
01034 }
01035 }
01036 }
01037
01038 cstringSList_free (badFields);
01039
01040 if (inUnion)
01041 {
01042 if (directUnion)
01043 {
01044 return (ynm_fromBool (hasOneDefined));
01045 }
01046 else
01047 {
01048 return (MAYBE);
01049 }
01050 }
01051 else
01052 {
01053 return (ynm_fromBool (!report || isOk));
01054 }
01055 }
01056 else
01057 {
01058 return YES;
01059 }
01060 }
01061 else if (ctype_isUnion (ct))
01062 {
01063 if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref))
01064 {
01065 return YES;
01066 }
01067 else
01068 {
01069 ctype tct = ctype_realType (sRef_getType (tref));
01070
01071 if (ctype_isKnown (tct) && ctype_match (ct, tct))
01072 {
01073 cstringSList goodFields = cstringSList_new ();
01074 bool isOk = FALSE;
01075 int nelements = sRefSet_size (sRef_derivedFields (fref));
01076
01077
01078
01079
01080
01081 if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
01082 {
01083 isOk = TRUE;
01084 }
01085
01086 sRefSet_realElements (sRef_derivedFields (fref), sr)
01087 {
01088 bool thisField;
01089
01090 if (sRef_isField (sr))
01091 {
01092 sRef fldref = sRef_makeField (tref, sRef_getField (sr));
01093
01094 thisField = ynm_toBoolStrict
01095 (checkCompletelyDefined
01096 (fexp, sr, texp, fldref, FALSE, inUnion,
01097 (nelements > 1 ? TRUE : FALSE),
01098 loc, transferType, depth + 1, FALSE));
01099
01100 if (thisField)
01101 {
01102 goodFields = cstringSList_add
01103 (goodFields, sRef_getField (sr));
01104 }
01105 }
01106 } end_sRefSet_realElements;
01107
01108 if (cstringSList_empty (goodFields)
01109 && !isOk
01110 && context_getFlag (FLG_UNIONDEF))
01111 {
01112 if (!inUnion)
01113 {
01114 if (transferType == TT_PARAMRETURN)
01115 {
01116 voptgenerror
01117 (FLG_UNIONDEF,
01118 message ("Union %q reachable from parameter has "
01119 "no defined field",
01120 sRef_unparse (fref)),
01121 loc);
01122 }
01123 else if (transferType == TT_LEAVETRANS)
01124 {
01125 voptgenerror
01126 (FLG_UNIONDEF,
01127 message ("Union %q has no defined field at scope exit",
01128 sRef_unparse (fref)),
01129 loc);
01130 }
01131 else if (transferType == TT_DOASSIGN
01132 || transferType == TT_FIELDASSIGN
01133 || transferType == TT_GLOBINIT)
01134 {
01135 ;
01136 }
01137 else
01138 {
01139 voptgenerror
01140 (FLG_UNIONDEF,
01141 message ("%s union %q has no defined field",
01142 transferType_unparse (transferType),
01143 sRef_unparse (fref)),
01144 loc);
01145 }
01146 }
01147 isOk = FALSE;
01148 }
01149
01150 cstringSList_free (goodFields);
01151 return ynm_fromBool (!report || isOk);
01152 }
01153 }
01154 }
01155 else
01156 {
01157 ;
01158 }
01159
01160 return YES;
01161 }
01162
01163
01164
01165
01166
01167 typedef enum {
01168 DSC_GLOB, DSC_LOCAL, DSC_PARAM, DSC_STRUCT
01169 } dscCode;
01170
01171 static cstring dscCode_unparse (dscCode desc)
01172 {
01173 switch (desc)
01174 {
01175 case DSC_GLOB:
01176 return cstring_makeLiteralTemp ("killed global");
01177 case DSC_LOCAL:
01178 return cstring_makeLiteralTemp ("variable declared in this scope");
01179 case DSC_PARAM:
01180 return cstring_makeLiteralTemp ("released storage");
01181 case DSC_STRUCT:
01182 return cstring_makeLiteralTemp ("released structure parameter");
01183 }
01184
01185 BADEXIT;
01186 }
01187
01188 static bool
01189 checkCompletelyDestroyed (exprNode p_fexp, sRef p_fref, bool p_topLevel,
01190 fileloc p_loc, int p_depth, dscCode p_desc);
01191
01192 bool checkGlobalDestroyed (sRef fref, fileloc loc)
01193 {
01194 return (checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
01195 loc, 0, DSC_GLOB));
01196 }
01197
01198 void checkLocalDestroyed (sRef fref, fileloc loc)
01199 {
01200 if (sRef_isObserver (fref) || sRef_isExposed (fref)
01201 || sRef_isPartial (fref))
01202 {
01203 ;
01204 }
01205 else
01206 {
01207 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
01208 loc, 0, DSC_LOCAL);
01209 }
01210 }
01211
01212 void checkStructDestroyed (sRef fref, fileloc loc)
01213 {
01214 if (sRef_isObserver (fref) || sRef_isExposed (fref)
01215 || sRef_isPartial (fref))
01216 {
01217 ;
01218 }
01219 else
01220 {
01221 (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE, loc, 0, DSC_STRUCT);
01222 }
01223 }
01224
01225 static bool
01226 checkCompletelyDestroyed (exprNode fexp, sRef fref, bool topLevel,
01227 fileloc loc, int depth,
01228 dscCode desc)
01229 {
01230 ctype ct;
01231
01232 if (depth > MAXDEPTH)
01233 {
01234 llquietbug (message ("checkCompletelyDestroyed: too deep: %s / %q",
01235 exprNode_unparse (fexp),
01236 sRef_unparseFull (fref)));
01237 return TRUE;
01238 }
01239
01240 if (!sRef_isKnown (fref)) return TRUE;
01241 if (usymtab_isProbableNull (fref)) return TRUE;
01242 if (!context_getFlag (FLG_COMPDESTROY)) return TRUE;
01243 if (!context_getFlag (FLG_MUSTFREE)) return TRUE;
01244
01245 ct = ctype_realType (sRef_getType (fref));
01246
01247 if (!topLevel)
01248 {
01249 bool error = FALSE;
01250
01251 if (sRef_isFresh (fref) || sRef_isOnly (fref))
01252 {
01253 error = TRUE;
01254
01255 if (sRef_isDead (fref)
01256 || sRef_isUnuseable (fref)
01257 || sRef_definitelyNull (fref)
01258 || sRef_isObserver (fref)
01259 || sRef_isExposed (fref))
01260 {
01261 error = FALSE;
01262 }
01263 }
01264
01265 if (error)
01266 {
01267 if (sRef_isPossiblyDead (fref) || sRef_isRelDef (fref))
01268 {
01269 if (exprNode_isDefined (fexp))
01270 {
01271 voptgenerror2
01272 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
01273 message ("Only storage %q (type %s) derived from %s "
01274 "may not have been released: %s",
01275 sRef_unparse (fref),
01276 ctype_unparse (sRef_getType (fref)),
01277 dscCode_unparse (desc),
01278 exprNode_unparse (fexp)),
01279 loc);
01280 }
01281 else
01282 {
01283 voptgenerror2
01284 (FLG_COMPDESTROY, FLG_STRICTDESTROY,
01285 message
01286 ("Only storage %q (type %s) derived from %s "
01287 "may not have been released",
01288 sRef_unparse (fref),
01289 ctype_unparse (sRef_getType (fref)),
01290 dscCode_unparse (desc)),
01291 loc);
01292 }
01293
01294 sRef_kill (fref, loc);
01295 }
01296 else
01297 {
01298 if (sRef_isStateUndefined (fref))
01299 {
01300 return TRUE;
01301 }
01302 else
01303 {
01304 if (exprNode_isDefined (fexp))
01305 {
01306 voptgenerror
01307 (FLG_COMPDESTROY,
01308 message ("Only storage %q (type %s) derived from %s "
01309 "is not released (memory leak): %s",
01310 sRef_unparse (fref),
01311 ctype_unparse (sRef_getType (fref)),
01312 dscCode_unparse (desc),
01313 exprNode_unparse (fexp)),
01314 loc);
01315 }
01316 else
01317 {
01318 voptgenerror
01319 (FLG_COMPDESTROY,
01320 message ("Only storage %q (type %s) derived from %s "
01321 "is not released (memory leak)",
01322 sRef_unparse (fref),
01323 ctype_unparse (sRef_getType (fref)),
01324 dscCode_unparse (desc)),
01325 loc);
01326 }
01327 }
01328 }
01329
01330 return FALSE;
01331 }
01332
01333 if (sRef_isAnyDefined (fref) || sRef_isDead (fref)
01334 || (sRef_isPdefined (fref)
01335 && sRefSet_isEmpty (sRef_derivedFields (fref))))
01336 {
01337 return TRUE;
01338 }
01339 }
01340
01341 if (ctype_isPointer (ct))
01342 {
01343 sRef fptr = sRef_constructDeadDeref (fref);
01344 bool res = checkCompletelyDestroyed (fexp, fptr, FALSE, loc,
01345 depth + 1, desc);
01346
01347 return res;
01348 }
01349 else if (ctype_isArray (ct))
01350 {
01351 if ((sRef_isStateUnknown (fref) || sRef_isAllocated (fref))
01352 && !sRef_hasDerived (fref))
01353 {
01354
01355
01356
01357
01358 return FALSE;
01359 }
01360 else
01361 {
01362 sRef farr = sRef_constructDeadDeref (fref);
01363
01364 return (checkCompletelyDestroyed (fexp, farr, FALSE, loc,
01365 depth + 1, desc));
01366 }
01367 }
01368 else if (ctype_isStruct (ct))
01369 {
01370
01371
01372
01373
01374 bool isOk = TRUE;
01375 uentryList fields = ctype_getFields (ct);
01376
01377 if (depth >= MAXDEPTH)
01378 {
01379 llquietbug (message ("checkCompletelyDestroyed (fields): too deep: %s / %q",
01380 exprNode_unparse (fexp),
01381 sRef_unparseFull (fref)));
01382
01383 return TRUE;
01384 }
01385 else
01386 {
01387 uentryList_elements (fields, ue)
01388 {
01389 sRef field = sRef_makeField (fref, uentry_rawName (ue));
01390
01391
01392
01393
01394
01395 isOk = (checkCompletelyDestroyed (fexp, field, FALSE, loc,
01396 depth + 1, desc)
01397 && isOk);
01398 } end_uentryList_elements;
01399 }
01400
01401 return isOk;
01402 }
01403 else
01404 {
01405 return TRUE;
01406 }
01407 }
01408
01409 void
01410 checkReturnTransfer (exprNode fexp, uentry rval)
01411 {
01412 sRef uref = uentry_getSref (rval);
01413 sRef rref = sRef_makeNew (sRef_getType (uref), uref, cstring_undefined);
01414
01415 if (sRef_isStateSpecial (rref))
01416 {
01417 uentry fcn = context_getHeader ();
01418 sRef fref = exprNode_getSref (fexp);
01419 specialClauses clauses = uentry_getSpecialClauses (fcn);
01420
01421 specialClauses_postElements (clauses, cl)
01422 {
01423 sRefSet refs = specialClause_getRefs (cl);
01424 sRefTest tst = specialClause_getPostTestFunction (cl);
01425 sRefMod modf = specialClause_getReturnEffectFunction (cl);
01426
01427 sRefSet_elements (refs, el)
01428 {
01429 sRef base = sRef_getRootBase (el);
01430
01431 if (sRef_isResult (base))
01432 {
01433 sRef sr = sRef_fixBase (el, fref);
01434
01435 if (tst != NULL && !(tst (sr)))
01436 {
01437 if (optgenerror
01438 (specialClause_postErrorCode (cl),
01439 message ("%s storage %q corresponds to "
01440 "storage listed in %q clause: %s",
01441 specialClause_postErrorString (cl, sr),
01442 sRef_unparse (sr),
01443 specialClause_unparseKind (cl),
01444 exprNode_unparse (fexp)),
01445 exprNode_loc (fexp)))
01446 {
01447 sRefShower ss = specialClause_getPostTestShower (cl);
01448
01449 if (ss != NULL)
01450 {
01451 ss (sr);
01452 }
01453 }
01454 }
01455
01456 if (modf != NULL)
01457 {
01458 modf (sr, exprNode_loc (fexp));
01459 }
01460 }
01461 else
01462 {
01463
01464
01465
01466 }
01467 } end_sRefSet_elements ;
01468 } end_specialClauses_postElements ;
01469
01470 (void) checkTransfer (fexp, fref,
01471 exprNode_undefined, rref,
01472 exprNode_loc (fexp), TT_FCNRETURN);
01473 }
01474 else
01475 {
01476 if (ctype_isRealSU (exprNode_getType (fexp)))
01477 {
01478 sRef fref = exprNode_getSref (fexp);
01479
01480 checkStructTransfer (exprNode_undefined, rref,
01481 fexp, fref,
01482 exprNode_loc (fexp),
01483 TT_FCNRETURN);
01484 }
01485 else
01486 {
01487 (void) checkTransfer (fexp, exprNode_getSref (fexp),
01488 exprNode_undefined, rref,
01489 exprNode_loc (fexp), TT_FCNRETURN);
01490 }
01491 }
01492 }
01493
01494 static void
01495 checkPassSpecialClauses (uentry ue, exprNode fexp, sRef fref, int argno)
01496 {
01497 specialClauses clauses = uentry_getSpecialClauses (ue);
01498
01499 DPRINTF (("Check pass special: %s / %s",
01500 exprNode_unparse (fexp), sRef_unparseFull (fref)));
01501
01502 specialClauses_preElements (clauses, cl)
01503 {
01504 sRefSet refs = specialClause_getRefs (cl);
01505 sRefTest tst = specialClause_getPreTestFunction (cl);
01506 sRefMod modf = specialClause_getEffectFunction (cl);
01507
01508 sRefSet_elements (refs, el)
01509 {
01510 sRef base = sRef_getRootBase (el);
01511
01512 if (sRef_isResult (base))
01513 {
01514 ;
01515 }
01516 else if (sRef_isParam (base))
01517 {
01518 if (sRef_getParam (base) == argno - 1)
01519 {
01520 sRef sb;
01521
01522 DPRINTF (("Fix base: %s / %s",
01523 sRef_unparseFull (el),
01524 sRef_unparseFull (fref)));
01525
01526 sb = sRef_fixBase (el, fref);
01527
01528 if (tst != NULL && !(tst(sb)))
01529 {
01530 voptgenerror
01531 (specialClause_preErrorCode (cl),
01532 message ("%s storage %qcorresponds to "
01533 "storage listed in %q clause of "
01534 "called function: %s",
01535 specialClause_preErrorString (cl, sb),
01536 sRef_unparseOpt (sb),
01537 specialClause_unparseKind (cl),
01538 exprNode_unparse (fexp)),
01539 exprNode_loc (fexp));
01540 }
01541
01542 if (modf != NULL)
01543 {
01544 DPRINTF (("Fixing: %s", sRef_unparseFull (sb)));
01545 modf (sb, exprNode_loc (fexp));
01546 DPRINTF (("==> %s", sRef_unparseFull (sb)));
01547 }
01548 }
01549 }
01550 else
01551 {
01552 BADBRANCH;
01553 }
01554 } end_sRefSet_elements ;
01555 } end_specialClauses_preElements ;
01556
01557 DPRINTF (("After: %s", sRef_unparseFull (fref)));
01558 }
01559
01560
01561
01562
01563
01564 void
01565 checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
01566 exprNode fcn, int argno, int totargs)
01567 {
01568 sRef tref = uentry_getSref (arg);
01569 sRef fref = exprNode_getSref (fexp);
01570 bool isOut = FALSE;
01571 bool isPartial = FALSE;
01572 bool isImpOut = FALSE;
01573 ctype ct = uentry_getType (arg);
01574
01575 DPRINTF (("Check pass: %s -> %s",
01576 sRef_unparseFull (fref),
01577 sRef_unparseFull (tref)));
01578
01579 atFunction = fcn;
01580 atArgNo = argno;
01581 atNumArgs = totargs;
01582
01583 if (ctype_isElips (ct))
01584 {
01585 ct = ctype_unknown;
01586 }
01587
01588 if (!ctype_isElips (ct) &&
01589 (ctype_isVoidPointer (ct) && uentry_isOut (arg) && sRef_isOnly (tref)))
01590 {
01591 if (ctype_isRealAP (ct))
01592 {
01593 if (sRef_aliasCheckSimplePred (sRef_isDead, fref))
01594 {
01595 if (optgenerror
01596 (FLG_USERELEASED,
01597 message ("Dead storage %qpassed as out parameter: %s",
01598 sRef_unparseOpt (fref),
01599 exprNode_unparse (fexp)),
01600 exprNode_loc (fexp)))
01601 {
01602 if (sRef_isDead (fref))
01603 {
01604 sRef_showStateInfo (fref);
01605 }
01606 }
01607
01608 sRef_setAllocated (fref, exprNode_loc (fexp));
01609 }
01610 else if (context_getFlag (FLG_STRICTUSERELEASED)
01611 && sRef_aliasCheckSimplePred (sRef_isPossiblyDead, fref))
01612 {
01613 if (optgenerror2
01614 (FLG_USERELEASED, FLG_STRICTUSERELEASED,
01615 message ("Possibly dead storage %qpassed as out parameter: %s",
01616 sRef_unparseOpt (fref),
01617 exprNode_unparse (fexp)),
01618 exprNode_loc (fexp)))
01619 {
01620 if (sRef_isPossiblyDead (fref))
01621 {
01622 sRef_showStateInfo (fref);
01623 }
01624 }
01625
01626 sRef_setAllocated (fref, exprNode_loc (fexp));
01627 }
01628 else if (sRef_aliasCheckSimplePred (sRef_isStateUndefined, fref)
01629 || sRef_aliasCheckSimplePred (sRef_isUnuseable, fref))
01630 {
01631 voptgenerror
01632 (FLG_USEDEF,
01633 message ("Unallocated storage %qpassed as out parameter: %s",
01634 sRef_unparseOpt (fref),
01635 exprNode_unparse (fexp)),
01636 exprNode_loc (fexp));
01637
01638 sRef_setAllocated (fref, exprNode_loc (fexp));
01639 }
01640 else
01641 {
01642 ;
01643 }
01644 }
01645
01646 (void) checkCompletelyDestroyed (fexp, fref, TRUE, exprNode_loc (fexp),
01647 0, DSC_PARAM);
01648
01649
01650 sRef_setDefined (fref, exprNode_loc (fexp));
01651 }
01652 else if (uentry_isOut (arg))
01653 {
01654 if (ctype_isRealAP (ct)
01655 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
01656 {
01657 voptgenerror
01658 (FLG_USEDEF,
01659 message ("Unallocated storage %qpassed as out parameter: %s",
01660 sRef_unparseOpt (fref),
01661 exprNode_unparse (fexp)),
01662 exprNode_loc (fexp));
01663 sRef_setAllocated (fref, exprNode_loc (fexp));
01664 }
01665 isOut = TRUE;
01666 }
01667 else if (uentry_isPartial (arg))
01668 {
01669 if (ctype_isRealAP (ct)
01670 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
01671 {
01672 voptgenerror
01673 (FLG_USEDEF,
01674 message ("Unallocated storage %qpassed as partial parameter: %s",
01675 sRef_unparseOpt (fref),
01676 exprNode_unparse (fexp)),
01677 exprNode_loc (fexp));
01678 sRef_setAllocated (fref, exprNode_loc (fexp));
01679 }
01680 isPartial = TRUE;
01681 }
01682 else if (uentry_isStateSpecial (arg))
01683 {
01684 uentry ue = exprNode_getUentry (fcn);
01685
01686 if (ctype_isRealAP (ct)
01687 && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
01688 {
01689 voptgenerror
01690 (FLG_USEDEF,
01691 message ("Unallocated storage %qpassed as special parameter: %s",
01692 sRef_unparseOpt (fref),
01693 exprNode_unparse (fexp)),
01694 exprNode_loc (fexp));
01695 sRef_setAllocated (fref, exprNode_loc (fexp));
01696 }
01697
01698 if (uentry_hasSpecialClauses (ue))
01699 {
01700 checkPassSpecialClauses (ue, fexp, fref, argno);
01701 }
01702
01703 return;
01704 }
01705 else if (sRef_isStateDefined (tref))
01706 {
01707 exprNode_checkUseParam (fexp);
01708 }
01709 else
01710 {
01711 if (isSpec || (!context_getFlag (FLG_IMPOUTS)))
01712 {
01713 exprNode_checkUseParam (fexp);
01714 }
01715 else
01716 {
01717 if (!sRef_isMacroParamRef (fref)
01718 && (ctype_isRealAP (ct)))
01719 {
01720 if (sRef_isAddress (fref))
01721 {
01722 if (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref))
01723 {
01724 voptgenerror
01725 (FLG_USEDEF,
01726 message
01727 ("Unallocated address %qpassed as implicit "
01728 "out parameter: %s",
01729 sRef_unparseOpt (fref),
01730 exprNode_unparse (fexp)),
01731 exprNode_loc (fexp));
01732 sRef_setAllocated (fref, exprNode_loc (fexp));
01733 }
01734 }
01735
01736
01737 tref = sRef_copy (tref);
01738 sRef_setAllocated (tref, exprNode_loc (fexp));
01739
01740 isOut = TRUE;
01741 isImpOut = TRUE;
01742 }
01743 else
01744 {
01745 exprNode_checkUseParam (fexp);
01746 }
01747 }
01748 }
01749
01750 if (sRef_isNew (fref))
01751 {
01752 alkind tkind = sRef_getAliasKind (tref);
01753
01754 if ((sRef_isFresh (fref) || sRef_isOnly (fref))
01755 && !alkind_isOnly (tkind)
01756 && !alkind_isKeep (tkind)
01757 && !alkind_isOwned (tkind)
01758 && !alkind_isError (tkind)
01759 && !uentry_isReturned (arg))
01760
01761 {
01762 voptgenerror
01763 (FLG_MUSTFREE,
01764 message ("New fresh storage %qpassed as %s (not released): %s",
01765 sRef_unparseOpt (fref),
01766 alkind_unparse (sRef_getAliasKind (tref)),
01767 exprNode_unparse (fexp)),
01768 exprNode_loc (fexp));
01769 }
01770 else
01771 {
01772 if (sRef_isNewRef (fref) && !sRef_isKillRef (tref))
01773 {
01774 alkind ak = sRef_getAliasKind (tref);
01775
01776 if (!alkind_isError (ak))
01777 {
01778 voptgenerror
01779 (FLG_MUSTFREE,
01780 message ("New reference %qpassed as %s (not released): %s",
01781 sRef_unparseOpt (fref),
01782 alkind_unparse (sRef_getAliasKind (tref)),
01783 exprNode_unparse (fexp)),
01784 exprNode_loc (fexp));
01785 }
01786 }
01787 }
01788 }
01789
01790 (void) checkTransfer (fexp, exprNode_getSref (fexp),
01791 exprNode_undefined, tref,
01792 exprNode_loc (fexp), TT_FCNPASS);
01793
01794 setCodePoint ();
01795 fref = exprNode_getSref (fexp);
01796
01797 if (isOut && !sRef_isDead (fref) && !sRef_isPossiblyDead (fref))
01798 {
01799 sRef base;
01800
01801 if (ctype_isRealAP (sRef_getType (fref)))
01802 {
01803 base = sRef_makePointer (fref);
01804 }
01805 else
01806 {
01807 base = fref;
01808 }
01809
01810 if (isImpOut)
01811 {
01812 exprNode_checkMSet (fexp, base);
01813 }
01814 else
01815 {
01816 exprNode_checkSet (fexp, base);
01817 }
01818
01819 if (sRef_isValid (base))
01820 {
01821 setCodePoint ();
01822
01823 sRef_clearDerived (base);
01824 sRef_setDefined (base, exprNode_loc (fexp));
01825 usymtab_clearAlias (base);
01826 sRef_setNullUnknown (base, exprNode_loc (fexp));
01827 }
01828 }
01829
01830 if (isPartial)
01831 {
01832 if (sRef_isValid (fref))
01833 {
01834 sRef_setPartial (fref, exprNode_loc (fexp));
01835 }
01836 }
01837
01838 atFunction = exprNode_undefined;
01839 atArgNo = 0;
01840 atNumArgs = 0;
01841
01842
01843
01844
01845 uentry_fixupSref (arg);
01846
01847 setCodePoint ();
01848
01849 DPRINTF (("Check pass: ==> %s",
01850 sRef_unparseFull (fref)));
01851 }
01852
01853 void
01854 checkGlobReturn (uentry glob)
01855 {
01856 sRef_protectDerivs ();
01857 checkGlobTrans (glob, TT_GLOBRETURN);
01858 sRef_clearProtectDerivs ();
01859 }
01860
01861 void checkParamReturn (uentry actual)
01862 {
01863 checkLeaveTrans (actual, TT_PARAMRETURN);
01864 }
01865
01866 void checkLoseRef (uentry actual)
01867 {
01868 checkLeaveTrans (actual, TT_LEAVETRANS);
01869 }
01870
01871 static void
01872 checkLeaveTrans (uentry actual, transferKind transferType)
01873 {
01874 sRef aref = uentry_getSref (actual);
01875 sRef origref = uentry_getOrigSref (actual);
01876
01877 if (transferType == TT_PARAMRETURN
01878 && (sRef_isKeep (origref) || sRef_isOnly (origref)
01879 || sRef_isOwned (origref)))
01880 {
01881
01882 }
01883 else
01884 {
01885 if (sRef_isNSLocalVar (origref))
01886 {
01887 ;
01888 }
01889 else
01890 {
01891 (void) checkCompletelyDefined (exprNode_undefined, aref,
01892 exprNode_undefined, origref,
01893 TRUE, FALSE, FALSE,
01894 g_currentloc, transferType,
01895 0, TRUE);
01896 }
01897 }
01898 }
01899
01900 static void
01901 checkGlobTrans (uentry glob, transferKind type)
01902 {
01903 sRef eref = uentry_getOrigSref (glob);
01904
01905 (void) checkCompletelyDefined (exprNode_undefined, uentry_getSref (glob),
01906 exprNode_undefined, eref,
01907 TRUE, FALSE, FALSE,
01908 g_currentloc, type, 0, TRUE);
01909 }
01910
01911
01912
01913
01914
01915
01916 static void
01917 fixAssignLhs (sRef s)
01918 {
01919 sRef_resetStateComplete (s);
01920 }
01921
01922 static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srhs,
01923 fileloc loc,
01924 transferKind tt)
01925 {
01926 ctype st = ctype_realType (sRef_getType (srhs));
01927
01928 if (ctype_isSU (st) && ctype_isRealSU (sRef_getType (slhs))
01929 && ctype_match (sRef_getType (slhs), st))
01930 {
01931 if (tt == TT_DOASSIGN && sRef_isStateDefined (srhs))
01932 {
01933 sRef_setDefinedComplete (slhs, loc);
01934 }
01935
01936 if (sRef_isDependent (slhs)
01937 || sRef_isObserver (slhs)
01938 || sRef_isExposed (slhs))
01939 {
01940 ;
01941 }
01942 else
01943 {
01944 if (sRef_isLocalVar (slhs)
01945 && sRef_isGlobal (sRef_getRootBase (srhs)))
01946 {
01947 sRef_setDependent (slhs, exprNode_loc (lhs));
01948 }
01949 else
01950 {
01951 if (ctype_isUnion (st))
01952 {
01953 sRef_setDefState (slhs, sRef_getDefState (srhs),
01954 exprNode_loc (lhs));
01955
01956 sRefSet_realElements (sRef_derivedFields (srhs), sr)
01957 {
01958 if (sRef_isField (sr))
01959 {
01960 cstring fieldname = sRef_getField (sr);
01961 sRef lfld = sRef_makeField (slhs, fieldname);
01962
01963 (void) checkTransfer (rhs, sr, lhs, lfld,
01964 exprNode_loc (lhs), tt);
01965 }
01966 } end_sRefSet_realElements ;
01967 }
01968 else
01969 {
01970 uentryList fields = ctype_getFields (st);
01971
01972 uentryList_elements (fields, field)
01973 {
01974 sRef rfld = sRef_makeField (srhs, uentry_rawName (field));
01975 sRef lfld = sRef_makeField (slhs, uentry_rawName (field));
01976 (void) checkTransfer (rhs, rfld, lhs, lfld, exprNode_loc (lhs), tt);
01977 } end_uentryList_elements ;
01978 }
01979
01980 if (sRef_isOnly (srhs))
01981 {
01982 sRef_setKeptComplete (srhs, loc);
01983 }
01984 }
01985 }
01986 }
01987 }
01988
01989 void
01990 checkInitTransfer (exprNode lhs, exprNode rhs)
01991 {
01992 sRef slhs = exprNode_getSref (lhs);
01993
01994 if (sRef_isGlobal (slhs) || (!sRef_isCvar (slhs)))
01995 {
01996 (void) checkTransfer (rhs, exprNode_getSref (rhs),
01997 lhs, slhs, exprNode_loc (rhs), TT_GLOBINIT);
01998 }
01999 else
02000 {
02001 checkAssignTransfer (lhs, rhs);
02002 }
02003 }
02004
02005 void
02006 checkAssignTransfer (exprNode lhs, exprNode rhs)
02007 {
02008 sRef slhs = exprNode_getSref (lhs);
02009 sRef srhs = exprNode_getSref (rhs);
02010 sRef base = sRef_getBaseSafe (slhs);
02011 nstate ns;
02012
02013 DPRINTF (("Check assign: %s = %s", exprNode_unparse (lhs),
02014 exprNode_unparse (rhs)));
02015 DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
02016 DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
02017
02018 if (ctype_isRealSU (sRef_getType (srhs)))
02019 {
02020 checkStructTransfer (lhs, slhs, rhs, srhs, exprNode_loc (lhs), TT_FIELDASSIGN);
02021 }
02022 else
02023 {
02024 (void) checkTransfer (rhs, srhs, lhs, slhs,
02025 exprNode_loc (lhs), TT_DOASSIGN);
02026 }
02027
02028 if (sRef_isConst (srhs) && sRef_isLocalState (srhs))
02029 {
02030
02031 sRef_setAliasKind (slhs, AK_ERROR, fileloc_undefined);
02032 }
02033
02034 if (sRef_isValid (base) && sRef_isStateDefined (base))
02035 {
02036 sRef_setPdefined (base, g_currentloc);
02037 }
02038
02039 if (sRef_isPartial (srhs))
02040 {
02041 sRef_setPartial (slhs, exprNode_loc (rhs));
02042 }
02043
02044
02045 ns = sRef_getNullState (srhs);
02046
02047 if (nstate_possiblyNull (ns))
02048 {
02049 if (usymtab_isGuarded (srhs))
02050 {
02051 ns = NS_NOTNULL;
02052 }
02053 }
02054
02055 sRef_setNullStateInnerComplete (slhs, ns, exprNode_loc (rhs));
02056
02057 if (sRef_isExposed (srhs) || sRef_isObserver (srhs))
02058 {
02059 sRef_setExKind (slhs, sRef_getExKind (srhs), exprNode_loc (rhs));
02060 }
02061
02062 DPRINTF (("Done transfer: %s", sRef_unparseFull (slhs)));
02063 }
02064
02065 static void
02066 checkTransferNullAux (sRef fref, exprNode fexp, bool ffix,
02067 sRef tref, exprNode texp, bool tfix,
02068 fileloc loc, transferKind transferType)
02069 {
02070 alkind tkind = sRef_getAliasKind (tref);
02071 ctype ttyp = ctype_realType (sRef_getType (tref));
02072
02073 if (ctype_isUnknown (ttyp))
02074 {
02075 ttyp = exprNode_getType (texp);
02076
02077 if (ctype_isUnknown (ttyp))
02078 {
02079 ttyp = exprNode_getType (fexp);
02080
02081 if (ctype_isUnknown (ttyp))
02082 {
02083 ttyp = sRef_getType (fref);
02084 }
02085 }
02086 }
02087
02088 if (ctype_isFunction (ttyp) && (transferType == TT_FCNRETURN))
02089 {
02090 ttyp = ctype_returnValue (ttyp);
02091 }
02092
02093
02094
02095
02096
02097 if (sRef_possiblyNull (fref)
02098 && !usymtab_isGuarded (fref)
02099 && ctype_isRealAP (ttyp))
02100 {
02101 if (!alkind_isLocal (tkind) && !alkind_isFresh (tkind)
02102 && !sRef_perhapsNull (tref)
02103 && !(transferType == TT_DOASSIGN))
02104 {
02105 if (transferType == TT_GLOBINIT)
02106 {
02107 if (optgenerror
02108 (FLG_NULLASSIGN,
02109 message ("%s %q initialized to %s value: %q",
02110 sRef_getScopeName (tref),
02111 sRef_unparse (tref),
02112 sRef_nullMessage (fref),
02113 generateText (fexp, texp, tref, transferType)),
02114 loc))
02115 {
02116 sRef_showNullInfo (fref);
02117 sRef_setNullError (tref);
02118 }
02119 }
02120 else
02121 {
02122 if (optgenerror
02123 ((transferType == TT_FCNPASS) ? FLG_NULLPASS : FLG_NULLRET,
02124 message ("%q storage %q%s: %q",
02125 cstring_capitalize (sRef_nullMessage (fref)),
02126 sRef_unparseOpt (fref),
02127 transferNullMessage (transferType),
02128 generateText (fexp, texp, tref, transferType)),
02129 loc))
02130 {
02131 sRef_showNullInfo (fref);
02132 sRef_setNullError (fref);
02133 }
02134 }
02135 }
02136 else
02137 {
02138 ;
02139 }
02140 }
02141 }
02142
02143
02144 static void
02145 checkTransferAssignAux (sRef fref, exprNode fexp, bool ffix,
02146 sRef tref, exprNode texp, bool tfix,
02147 fileloc loc, transferKind transferType)
02148 {
02149 alkind tkind = sRef_getAliasKind (tref);
02150
02151
02152
02153
02154
02155
02156 if (sRef_sameName (fref, tref))
02157 {
02158 sRef_copyState (tref, fref);
02159 return;
02160 }
02161
02162 if ((alkind_isOnly (tkind) || alkind_isFresh (tkind)
02163 || alkind_isNewRef (tkind) || alkind_isOwned (tkind))
02164 && !(sRef_isDead (tref)
02165 || sRef_isStateUndefined (tref)
02166 || sRef_isUnuseable (tref)
02167 || sRef_isPartial (tref)
02168 || sRef_definitelyNull (tref)
02169 || sRef_isStackAllocated (tref)
02170 || sRef_isAllocIndexRef (tref))
02171 && !(sRef_same (fref, tref))
02172 && !(usymtab_isProbableNull (tref)))
02173 {
02174 if (context_getFlag (FLG_MUSTFREE))
02175 {
02176 if (canLoseReference (tref, loc))
02177 {
02178 ;
02179 }
02180 else
02181 {
02182 if (sRef_hasLastReference (tref))
02183 {
02184 if (optgenerror
02185 (FLG_MUSTFREE,
02186 message ("Last reference %q to %s storage %qnot released "
02187 "before assignment: %q",
02188 sRef_unparse (tref),
02189 alkind_unparse (tkind),
02190 sRef_unparseOpt (sRef_getAliasInfoRef (tref)),
02191 generateText (fexp, texp, tref, transferType)),
02192 loc))
02193 {
02194 sRef_showRefLost (tref);
02195 }
02196 }
02197 else
02198 {
02199 if (context_inGlobalScope ())
02200 {
02201
02202 }
02203 else
02204 {
02205
02206
02207
02208
02209
02210 if (alkind_isNewRef (tkind))
02211 {
02212 if (optgenerror
02213 (FLG_MUSTFREE,
02214 message
02215 ("%q %qnot released before assignment: %q",
02216 cstring_makeLiteral
02217 (alkind_isKillRef (sRef_getOrigAliasKind (tref))
02218 ? "Kill reference parameter" : "New reference"),
02219 sRef_unparseOpt (tref),
02220 generateText (fexp, texp, tref, transferType)),
02221 loc))
02222 {
02223 sRef_showAliasInfo (tref);
02224 sRef_setAliasKind (tref, AK_ERROR, loc);
02225 }
02226 }
02227 else if
02228 (!(sRef_isUnknownArrayFetch (tref)
02229 && !context_getFlag (FLG_STRICTDESTROY))
02230 && !sRef_isUnionField (tref)
02231 && !sRef_isRelDef (tref)
02232 && optgenerror
02233 (FLG_MUSTFREE,
02234 message
02235 ("%s storage %qnot released before assignment: %q",
02236 alkind_capName (tkind),
02237 sRef_unparseOpt (tref),
02238 generateText (fexp, texp, tref, transferType)),
02239 loc))
02240 {
02241 sRef_showAliasInfo (tref);
02242 }
02243 else
02244 {
02245 ;
02246 }
02247 }
02248 }
02249 }
02250 }
02251 }
02252
02253 fixAssignLhs (tref);
02254
02255 if (sRef_isRefCounted (tref))
02256 {
02257 if (sRef_isNewRef (fref))
02258 {
02259 sRef_setAliasKind (tref, AK_NEWREF, loc);
02260 }
02261 else if (sRef_isConst (fref))
02262 {
02263
02264 sRef_setAliasKind (tref, AK_ERROR, loc);
02265 }
02266 else
02267 {
02268 ;
02269 }
02270
02271 if (!sRef_isNSLocalVar (tref)
02272 && sRef_isRefCounted (fref)
02273 && sRef_isStateDefined (fref))
02274 {
02275 voptgenerror
02276 (FLG_NEWREFTRANS,
02277 message ("New reference %qto reference counted storage: %q",
02278 sRef_unparseOpt (tref),
02279 generateText (fexp, texp, tref, transferType)),
02280 loc);
02281 }
02282 }
02283
02284
02285
02286
02287
02288 if (sRef_isStack (fref)
02289 && !ctype_isSU (ctype_realType (sRef_getType (fref))))
02290 {
02291 sRef_setAliasKindComplete (tref, AK_STACK, loc);
02292 }
02293
02294 if (sRef_isNSLocalVar (tref)
02295 && !sRef_isOwned (tref)
02296 && ctype_isMutable (sRef_getType (tref)))
02297 {
02298 if (sRef_isOnly (fref) && sRef_isNew (fref))
02299 {
02300 if (!tfix)
02301 {
02302 sRef_setFresh (tref, loc);
02303 }
02304 }
02305 }
02306 }
02307
02308
02309
02310
02311
02312 static void
02313 checkOnlyTransferAux (sRef fref, exprNode fexp, bool ffix,
02314 sRef tref, exprNode texp, bool tfix,
02315 fileloc loc, transferKind transferType)
02316 {
02317 alkind tkind = sRef_getAliasKind (tref);
02318
02319 if (sRef_isExposed (tref) || sRef_isObserver (tref))
02320 {
02321 if (transferType == TT_FCNRETURN && sRef_isNew (fref)
02322 && !alkind_isError (tkind))
02323 {
02324 if (optgenerror
02325 (FLG_ONLYTRANS,
02326 message ("Only storage %q%q (will not be released): %q",
02327 sRef_unparseOpt (fref),
02328 transferErrorMessage (transferType, tkind),
02329 generateText (fexp, texp, tref, transferType)),
02330 loc))
02331 {
02332 sRef_showAliasInfo (fref);
02333 }
02334 }
02335
02336
02337 }
02338 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind) || alkind_isOwned (tkind))
02339 {
02340 ;
02341 }
02342 else if ((transferType == TT_FCNPASS)
02343 && (alkind_isUnknown (tkind)
02344 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
02345 {
02346 if (sRef_isFresh (fref)
02347 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
02348 {
02349 if (!ffix) sRef_setAliasKind (fref, AK_UNKNOWN, loc);
02350 }
02351 }
02352 else if (alkind_isLocal (tkind)
02353 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
02354 {
02355 if ((transferType == TT_DOASSIGN)
02356 && sRef_isNew (fref)
02357 && sRef_isOnly (fref))
02358 {
02359 bool error = FALSE;
02360
02361 if (alkind_isUnknown (tkind)
02362 && sRef_isGlobal (sRef_getRootBase (tref)))
02363 {
02364 if (optgenerror
02365 (FLG_ONLYUNQGLOBALTRANS,
02366 message ("Only storage %q%q: %q",
02367 sRef_unparseOpt (fref),
02368 transferErrorMessage (transferType, tkind),
02369 generateText (fexp, texp, tref, transferType)),
02370 loc))
02371 {
02372 sRef_showAliasInfo (fref);
02373 sRef_setAliasKind (tref, AK_ERROR, loc);
02374 error = TRUE;
02375 }
02376 }
02377
02378 if (!error && !ffix)
02379 {
02380 sRef_setFresh (tref, loc);
02381 }
02382 }
02383 else
02384 {
02385 if (alkind_isLocal (tkind))
02386 {
02387 if (sRef_sameName (tref, fref))
02388 {
02389 ;
02390 }
02391 else
02392 {
02393
02394
02395
02396
02397
02398
02399 if (!tfix && sRef_isThroughArrayFetch (fref)
02400 && context_getFlag (FLG_DEPARRAYS))
02401 {
02402 sRef_setDependent (tref, loc);
02403 }
02404 }
02405 }
02406 else
02407 {
02408 if (optgenerror
02409 (FLG_ONLYTRANS,
02410 message ("Only storage %q%q: %q",
02411 sRef_unparseOpt (fref),
02412 transferErrorMessage (transferType, tkind),
02413 generateText (fexp, texp, tref, transferType)),
02414 loc))
02415 {
02416 sRef_showAliasInfo (fref);
02417 }
02418 }
02419 }
02420 }
02421 else
02422 {
02423 if (alkind_isError (tkind)
02424 || (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT)))
02425 {
02426 flagcode_recordSuppressed (FLG_ONLYTRANS);
02427 }
02428 else
02429 {
02430 if ((alkind_isKept (tkind) || alkind_isStack (tkind)
02431 || alkind_isDependent (tkind))
02432 && sRef_isNSLocalVar (tref))
02433 {
02434 ;
02435 }
02436 else
02437 {
02438 if (optgenerror
02439 (FLG_ONLYTRANS,
02440 message ("Only storage %q%q: %q",
02441 sRef_unparseOpt (fref),
02442 transferErrorMessage (transferType, tkind),
02443 generateText (fexp, texp, tref, transferType)),
02444 loc))
02445 {
02446 sRef_showAliasInfo (fref);
02447 }
02448 }
02449 }
02450
02451 if (transferType == TT_DOASSIGN)
02452 {
02453
02454
02455
02456
02457 if (!ffix && sRef_isNSLocalVar (sRef_getRootBase (fref)))
02458 {
02459 sRef_clearAliasKind (fref);
02460 }
02461 }
02462 }
02463 }
02464
02465
02466
02467
02468
02469 static void
02470 checkOwnedTransferAux (sRef fref, exprNode fexp, bool ffix,
02471 sRef tref, exprNode texp, bool tfix,
02472 fileloc loc, transferKind transferType)
02473 {
02474 alkind tkind = sRef_getAliasKind (tref);
02475
02476 if (sRef_isExposed (tref) || sRef_isObserver (tref))
02477 {
02478 if (transferType == TT_FCNRETURN && sRef_isNew (fref))
02479 {
02480 if (optgenerror
02481 (FLG_OWNEDTRANS,
02482 message ("Owned storage %q%q (will not be released): %q",
02483 sRef_unparseOpt (fref),
02484 transferErrorMessage (transferType, tkind),
02485 generateText (fexp, texp, tref, transferType)),
02486 loc))
02487 {
02488 sRef_showAliasInfo (fref);
02489 }
02490 }
02491 }
02492 else if (alkind_isOnly (tkind) || alkind_isKeep (tkind)
02493 || alkind_isDependent (tkind)
02494 || alkind_isOwned (tkind))
02495 {
02496
02497 }
02498 else if (alkind_isLocal (tkind)
02499 || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
02500 {
02501 if ((transferType == TT_DOASSIGN)
02502 && sRef_isNew (fref) && sRef_isOnly (fref))
02503 {
02504 if (!tfix)
02505 {
02506 sRef_setFresh (tref, loc);
02507 }
02508 }
02509 else
02510 {
02511 }
02512 }
02513 else if ((transferType == TT_FCNPASS)
02514 && (alkind_isUnknown (tkind)
02515 || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
02516 {
02517 if (sRef_isFresh (fref)
02518 && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
02519 {
02520 if (!ffix) { sRef_clearAliasKind (fref); }
02521 }
02522 }
02523 else
02524 {
02525 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
02526 {
02527 flagcode_recordSuppressed (FLG_OWNEDTRANS);
02528 }
02529 else
02530 {
02531 if (alkind_isKept (tkind) && sRef_isNSLocalVar (tref))
02532 {
02533 ;
02534 }
02535 else
02536 {
02537 voptgenerror
02538 (FLG_OWNEDTRANS,
02539 message ("Owned storage %q%q: %q",
02540 sRef_unparseOpt (fref),
02541 transferErrorMessage (transferType, tkind),
02542 generateText (fexp, texp, tref, transferType)),
02543 loc);
02544 }
02545 }
02546
02547 if (transferType == TT_DOASSIGN)
02548 {
02549
02550
02551
02552
02553 if (!ffix) { sRef_clearAliasKind (fref); }
02554 }
02555 }
02556 }
02557
02558 static void
02559 checkFreshTransferAux (sRef fref, exprNode fexp, bool ffix,
02560 sRef tref, exprNode texp, bool tfix,
02561 fileloc loc, transferKind transferType)
02562 {
02563 alkind tkind = sRef_getAliasKind (tref);
02564
02565
02566
02567
02568
02569 if (transferType == TT_FCNRETURN
02570 && !(alkind_isOnly (tkind) || alkind_isNewRef (tkind)))
02571 {
02572 if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
02573 {
02574 flagcode_recordSuppressed (FLG_NEWREFTRANS);
02575 }
02576 else
02577 {
02578 if (alkind_isError (tkind))
02579 {
02580 if (!ffix)
02581 {
02582 sRef_killComplete (fref, loc);
02583 }
02584 }
02585 else if (alkind_isRefCounted (tkind))
02586 {
02587 if (optgenerror
02588 (FLG_NEWREFTRANS,
02589 message
02590 ("New reference returned without newref qualifier: %q",
02591 generateText (fexp, texp, tref, transferType)),
02592 loc))
02593 {
02594 sRef_showAliasInfo (fref);
02595 sRef_killComplete (fref, loc);
02596 }
02597 }
02598 else
02599 {
02600 if (optgenerror
02601 (FLG_FRESHTRANS,
02602 message ("Fresh storage %q (should be only): %q",
02603 transferErrorMessage (transferType, tkind),
02604 generateText (fexp, texp, tref, transferType)),
02605 loc))
02606 {
02607 sRef_showAliasInfo (fref);
02608 sRef_killComplete (fref, loc);
02609 }
02610 }
02611 }
02612 }
02613
02614
02615
02616
02617
02618
02619
02620 if (alkind_isOnly (tkind))
02621 {
02622 if (transferType == TT_DOASSIGN && !sRef_isGlobal (tref))
02623 {
02624 if (!ffix)
02625 {
02626 if (!sRef_isNSLocalVar (tref))
02627 {
02628 sRef_setKeptComplete (fref, loc);
02629 }
02630 }
02631 }
02632 else
02633 {
02634 if (sRef_isConst (fref))
02635 {
02636 ;
02637 }
02638 else
02639 {
02640 if (!ffix)
02641 {
02642 sRef_killComplete (fref, loc);
02643 }
02644 }
02645 }
02646 }
02647 else if (alkind_isOwned (tkind))
02648 {
02649 if (!ffix)
02650 {
02651 sRef_setDependentComplete (fref, loc);
02652 }
02653 }
02654 else if (alkind_isRefCounted (tkind)
02655 && (transferType == TT_FCNRETURN) && sRef_isFresh (fref))
02656 {
02657 if (!ffix)
02658 {
02659 sRef_killComplete (fref, loc);
02660 }
02661 }
02662 else if (alkind_isKeep (tkind))
02663 {
02664 if (!ffix)
02665 {
02666 if (!sRef_isNSLocalVar (tref))
02667 {
02668 sRef_setKeptComplete (fref, loc);
02669 }
02670 }
02671 }
02672 else if (alkind_isShared (tkind))
02673 {
02674 if (!ffix) { sRef_setShared (fref, loc); }
02675 }
02676 else if (alkind_isLocal (tkind) || alkind_isUnknown (tkind))
02677 {
02678 if (transferType == TT_DOASSIGN || transferType == TT_FCNRETURN)
02679 {
02680
02681
02682
02683
02684 if (!tfix)
02685 {
02686 sRef_setOwned (tref, loc);
02687 }
02688
02689 if (!ffix && !tfix)
02690 {
02691 sRef_setDependentComplete (fref, loc);
02692 }
02693
02694
02695 }
02696 else
02697 {
02698 if (context_getFlag (FLG_PASSUNKNOWN))
02699 {
02700 sRef_clearAliasKind (fref);
02701 }
02702 }
02703 }
02704 else
02705 {
02706 ;
02707 }
02708 }
02709
02710 static void
02711 checkTransferExposure (sRef fref, exprNode fexp, bool ffix,
02712 sRef tref, exprNode texp, bool tfix,
02713 fileloc loc,
02714 transferKind transferType)
02715 {
02716 alkind fkind = sRef_getAliasKind (fref);
02717 alkind tkind = sRef_getAliasKind (tref);
02718 exkind tekind = sRef_getExKind (tref);
02719
02720 if (sRef_isObserver (fref) && ctype_isMutable (sRef_getType (fref)))
02721 {
02722
02723
02724
02725
02726
02727
02728
02729
02730 if (sRef_isExposed (tref) || sRef_isObserver (tref)
02731 || alkind_isLocal (tkind))
02732 {
02733
02734
02735 if ((transferType == TT_DOASSIGN) && alkind_isLocal (tkind))
02736 {
02737 if (!tfix) { sRef_setAliasKindComplete (tref, fkind, loc); }
02738 }
02739 }
02740 else
02741 {
02742 if (transferType == TT_FCNRETURN
02743 || transferType == TT_DOASSIGN
02744 || transferType == TT_FIELDASSIGN
02745 || transferType == TT_GLOBINIT)
02746 {
02747 bool hasError = FALSE;
02748
02749 if (exprNode_isStringLiteral (fexp)
02750 && transferType == TT_GLOBINIT)
02751 {
02752 hasError = optgenerror
02753 (FLG_READONLYTRANS,
02754 message ("Read-only string literal storage %q%q: %q",
02755 sRef_unparseOpt (fref),
02756 transferErrorExpMessage (transferType, tekind),
02757 generateText (fexp, texp, tref, transferType)),
02758 loc);
02759
02760 sRef_setAliasKind (fref, AK_ERROR, fileloc_undefined);
02761 }
02762 else
02763 {
02764 if ((transferType == TT_DOASSIGN
02765 || transferType == TT_FIELDASSIGN)
02766 && (sRef_isNSLocalVar (tref)
02767 || (exprNode_isStringLiteral (fexp)
02768 && ctype_isRealArray (exprNode_getType (texp)))))
02769 {
02770 ;
02771
02772 }
02773 else
02774 {
02775 if (exprNode_isStringLiteral (fexp))
02776 {
02777 hasError = optgenerror
02778 (FLG_READONLYTRANS,
02779 message
02780 ("Read-only string literal storage %q%q: %q",
02781 sRef_unparseOpt (fref),
02782 transferErrorExpMessage (transferType, tekind),
02783 generateText (fexp, texp, tref, transferType)),
02784 loc);
02785
02786 }
02787
02788 if (!hasError)
02789 {
02790 hasError = optgenerror
02791 (FLG_OBSERVERTRANS,
02792 message
02793 ("Observer storage %q%q: %q",
02794 sRef_unparseOpt (fref),
02795 transferErrorExpMessage (transferType, tekind),
02796 generateText (fexp, texp, tref, transferType)),
02797 loc);
02798 }
02799 }
02800 }
02801
02802 if (hasError)
02803 {
02804 if (transferType != TT_GLOBINIT)
02805 {
02806 sRef_showExpInfo (fref);
02807 sRef_setAliasKind (tref, AK_ERROR, loc);
02808 }
02809 }
02810 else
02811 {
02812 if (transferType == TT_DOASSIGN && !tfix)
02813 {
02814 DPRINTF (("Setting unknown!"));
02815
02816 }
02817 }
02818 }
02819 else
02820 {
02821 llassert (transferType == TT_FCNPASS);
02822
02823 if (alkind_isTemp (tkind)
02824 || alkind_isDependent (tkind)
02825 || alkind_isRefCounted (tkind))
02826 {
02827 ;
02828 }
02829 else
02830 {
02831 if (!alkind_isError (tkind))
02832 {
02833 if (optgenerror
02834 (FLG_OBSERVERTRANS,
02835 message ("Observer storage %q%q: %q",
02836 sRef_unparseOpt (fref),
02837 transferErrorMessage (transferType, tkind),
02838 generateText (fexp, texp, tref, transferType)),
02839 loc))
02840 {
02841 sRef_showExpInfo (fref);
02842 sRef_clearAliasState (fref, loc);
02843 }
02844 }
02845 }
02846 }
02847 }
02848 }
02849 else if (sRef_isExposed (fref) && ctype_isMutable (sRef_getType (fref)))
02850 {
02851 if (transferType == TT_FCNRETURN)
02852 {
02853 if (!(sRef_isExposed (tref) || sRef_isObserver (tref)
02854 || sRef_isParam (fref)))
02855 {
02856 if (optgenerror
02857 (FLG_EXPOSETRANS,
02858 message ("Exposed storage %q%q: %q",
02859 sRef_unparseOpt (fref),
02860 transferErrorExpMessage (transferType, tekind),
02861 generateText (fexp, texp, tref, transferType)),
02862 loc))
02863 {
02864 sRef_showExpInfo (fref);
02865 }
02866 }
02867 }
02868 else if (transferType == TT_FCNPASS)
02869 {
02870 if (!(sRef_isExposed (tref)
02871 || sRef_isObserver (tref)
02872 || (alkind_isUnknown (tkind)
02873 || alkind_isDependent (tkind)
02874 || alkind_isTemp (tkind)
02875 || alkind_isKillRef (tkind)
02876 || alkind_isRefCounted (tkind))))
02877 {
02878 if (alkind_isUnique (tkind) || alkind_isError (tkind))
02879 {
02880 }
02881 else
02882 {
02883 if (optgenerror
02884 (FLG_EXPOSETRANS,
02885 message ("Exposed storage %q%q: %q",
02886 sRef_unparseOpt (fref),
02887 transferErrorMessage (transferType, tkind),
02888 generateText (fexp, texp, tref, transferType)),
02889 loc))
02890 {
02891 sRef_showExpInfo (fref);
02892 sRef_clearAliasState (fref, loc);
02893 }
02894 }
02895
02896 }
02897 else
02898 {
02899 ;
02900 }
02901 }
02902 else if (transferType == TT_DOASSIGN)
02903 {
02904 if (!(sRef_isExposed (tref)
02905 || !sRef_isCvar (tref)
02906 || (alkind_isUnknown (tkind)
02907 || alkind_isDependent (tkind)
02908 || alkind_isRefCounted (tkind)
02909 || alkind_isNewRef (tkind)
02910 || alkind_isFresh (tkind)
02911 || alkind_isLocal (tkind))))
02912 {
02913 if (optgenerror
02914 (FLG_EXPOSETRANS,
02915 message ("Exposed storage %q%q: %q",
02916 sRef_unparseOpt (fref),
02917 transferErrorExpMessage (transferType, tekind),
02918 generateText (fexp, texp, tref, transferType)),
02919 loc))
02920 {
02921 sRef_showExpInfo (fref);
02922 }
02923 }
02924 if (!tfix) { sRef_setExposed (tref, loc); }
02925 }
02926 else
02927 {
02928 llassert (transferType == TT_GLOBPASS
02929 || transferType == TT_GLOBRETURN
02930 || transferType == TT_PARAMRETURN
02931 || transferType == TT_LEAVETRANS
02932 || transferType == TT_GLOBINIT);
02933 }
02934 }
02935 else
02936 {
02937 ;
02938 }
02939 }
02940
02941
02942
02943
02944
02945
02946
02947
02948 static void
02949 checkTransferAux (exprNode fexp, sRef fref, bool ffix,
02950 exprNode texp, sRef tref, bool tfix,
02951 fileloc loc, transferKind transferType)
02952 {
02953 alkind fkind;
02954 alkind tkind;
02955 bool isassign = (transferType == TT_DOASSIGN);
02956 bool isfieldassign = (transferType == TT_FIELDASSIGN);
02957 bool iseitherassign = isassign || (transferType == TT_FIELDASSIGN);
02958 bool isfcnpass = (transferType == TT_FCNPASS);
02959 bool isfcnreturn = (transferType == TT_FCNRETURN);
02960
02961 setCodePoint ();
02962
02963 if (!ffix && !tfix)
02964 {
02965 setCodePoint ();
02966 checkTransferNullAux (fref, fexp, ffix, tref, texp, tfix,
02967 loc, transferType);
02968 }
02969
02970 if (isassign)
02971 {
02972 setCodePoint ();
02973 checkTransferAssignAux (fref, fexp, ffix, tref, texp, tfix,
02974 loc, transferType);
02975 }
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985 if (!ffix && !tfix)
02986 {
02987 bool defok = TRUE;
02988
02989 if (!iseitherassign
02990 || (!sRef_isNSLocalVar (tref)
02991 && (sRef_isAnyDefined (tref) || !sRef_stateKnown (tref))))
02992 {
02993 setCodePoint ();
02994
02995 if (!ynm_toBoolRelaxed
02996 (checkCompletelyDefined (fexp, fref, texp, tref,
02997 TRUE, FALSE, FALSE,
02998 loc, transferType, 0, TRUE)))
02999 {
03000 defok = FALSE;
03001 }
03002 }
03003
03004 setCodePoint ();
03005
03006 if (defok && iseitherassign)
03007 {
03008 sRef_setDefState (tref, sRef_getDefState (fref), loc);
03009 }
03010 }
03011
03012
03013
03014
03015
03016
03017 setCodePoint ();
03018 checkTransferExposure (fref, fexp, ffix, tref, texp, tfix,
03019 loc, transferType);
03020
03021 fkind = sRef_getAliasKind (fref);
03022 tkind = sRef_getAliasKind (tref);
03023
03024
03025
03026
03027
03028 if (alkind_isOnly (fkind))
03029 {
03030 setCodePoint ();
03031 checkOnlyTransferAux (fref, fexp, ffix,
03032 tref, texp, tfix,
03033 loc, transferType);
03034 }
03035 else if (alkind_isFresh (fkind))
03036 {
03037 setCodePoint ();
03038 checkFreshTransferAux (fref, fexp, ffix,
03039 tref, texp, tfix,
03040 loc, transferType);
03041 }
03042 else if (alkind_isOwned (fkind))
03043 {
03044 setCodePoint ();
03045 checkOwnedTransferAux (fref, fexp, ffix,
03046 tref, texp, tfix,
03047 loc, transferType);
03048 }
03049 else if (alkind_isDependent (fkind))
03050 {
03051 setCodePoint ();
03052 if (isfcnreturn &&
03053 (sRef_isExposed (tref) || sRef_isObserver (tref)))
03054 {
03055 ;
03056 }
03057 else if ((alkind_isOnly (tkind) || alkind_isKeep (tkind)
03058 || alkind_isOwned (tkind))
03059 || (!isfcnpass && alkind_isTemp (tkind)))
03060 {
03061 bool error = TRUE;
03062
03063 if (sRef_isLocalVar (fref))
03064 {
03065 sRef depRef = dependentReference (fref);
03066
03067 if (sRef_isValid (depRef) && sRef_isLocalVar (depRef))
03068 {
03069 error = FALSE;
03070 sRef_kill (depRef, loc);
03071 sRef_kill (fref, loc);
03072 }
03073
03074 }
03075
03076 if (isfieldassign)
03077 {
03078 error = FALSE;
03079 }
03080
03081 if (canLoseLocalReference (fref, loc))
03082 {
03083 ;
03084 }
03085 else
03086 {
03087 if (error &&
03088 (optgenerror
03089 (FLG_DEPENDENTTRANS,
03090 message ("%s storage %q%q: %q",
03091 alkind_capName (fkind),
03092 sRef_unparseOpt (fref),
03093 transferErrorMessage (transferType, tkind),
03094 generateText (fexp, texp, tref, transferType)),
03095 loc)))
03096 {
03097 DPRINTF (("Here: %s / %s",
03098 sRef_unparseFull (fref),
03099 sRef_unparseFull (tref)));
03100
03101 sRef_showAliasInfo (fref);
03102 }
03103 }
03104 }
03105 else
03106 {
03107 if (isassign && (alkind_isFresh (tkind) || alkind_isLocal (tkind)))
03108 {
03109 if (!tfix && !ffix)
03110 {
03111 sRef_setDependent (tref, loc);
03112 }
03113 }
03114 }
03115 }
03116 else if (alkind_isShared (fkind))
03117 {
03118 setCodePoint ();
03119
03120
03121
03122
03123 if (alkind_isOnly (tkind)
03124 || (!isfcnpass
03125 && (!(sRef_isObserver (tref) || sRef_isExposed (tref))
03126 && alkind_isTemp (tkind))))
03127 {
03128 if (optgenerror
03129 (FLG_SHAREDTRANS,
03130 message ("%s storage %q%q: %q",
03131 alkind_capName (fkind),
03132 sRef_unparseOpt (fref),
03133 transferErrorMessage (transferType, tkind),
03134 generateText (fexp, texp, tref, transferType)),
03135 loc))
03136 {
03137 sRef_showAliasInfo (fref);
03138 }
03139 }
03140 else
03141 {
03142 if (alkind_isFresh (tkind) || alkind_isLocal (tkind))
03143 {
03144 sRef_setShared (tref, loc);
03145 }
03146 }
03147 }
03148 else if (alkind_isKeep (fkind))
03149 {
03150 setCodePoint ();
03151
03152 if (alkind_isKeep (tkind)
03153 || alkind_isLocal (tkind)
03154 || (isfcnreturn && sRef_isExposed (tref))
03155 || (iseitherassign
03156 && (alkind_isOnly (tkind) || alkind_isOwned (tkind))))
03157 {
03158 sRef_setKept (fref, loc);
03159 }
03160 else if (isfcnpass
03161 && (alkind_isTemp (tkind) || alkind_isOwned (tkind)))
03162 {
03163 ;
03164 }
03165 else
03166 {
03167 if (!alkind_isError (tkind))
03168 {
03169 if (optgenerror
03170 (FLG_KEEPTRANS,
03171 message ("%s storage %q: %q",
03172 alkind_capName (fkind),
03173 transferErrorMessage (transferType, tkind),
03174 generateText (fexp, texp, tref, transferType)),
03175 loc))
03176 {
03177 sRef_showAliasInfo (fref);
03178 }
03179 }
03180 }
03181 }
03182 else if (alkind_isTemp (fkind) || alkind_isKept (fkind))
03183 {
03184
03185
03186
03187
03188 if (alkind_isOnly (tkind)
03189 || alkind_isShared (tkind)
03190 || (alkind_isTemp (fkind)
03191 && !isfcnreturn && alkind_isDependent (tkind))
03192 || alkind_isOwned (tkind)
03193 || alkind_isKeep (tkind))
03194 {
03195 if (!exprNode_isNullValue (fexp)
03196 && (ctype_isMutable (exprNode_getType (fexp))
03197 || (ctype_isArray (exprNode_getType (fexp))
03198 && sRef_isParam (fref)))
03199 && (!iseitherassign || sRef_isReference (tref)))
03200 {
03201 if (sRef_isThroughArrayFetch (fref))
03202 {
03203 if (optgenerror2
03204 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
03205 FLG_STRICTUSERELEASED,
03206 message ("%s storage %q%q: %q",
03207 alkind_capName (fkind),
03208 sRef_unparseOpt (fref),
03209 transferErrorMessage (transferType, tkind),
03210 generateText (fexp, texp, tref, transferType)),
03211 loc))
03212 {
03213 sRef_showAliasInfo (fref);
03214 }
03215 }
03216 else
03217 {
03218 if (optgenerror
03219 (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
03220 message ("%s storage %q%q: %q",
03221 alkind_capName (fkind),
03222 sRef_unparseOpt (fref),
03223 transferErrorMessage (transferType, tkind),
03224 generateText (fexp, texp, tref, transferType)),
03225 loc))
03226 {
03227 sRef_showAliasInfo (fref);
03228 }
03229 }
03230 }
03231 }
03232 }
03233 else if (alkind_isRefCounted (fkind) || alkind_isKillRef (fkind))
03234 {
03235 if (alkind_isNewRef (tkind))
03236 {
03237
03238
03239
03240
03241 if (!sRef_isConst (fref))
03242 {
03243 voptgenerror
03244 (FLG_REFCOUNTTRANS,
03245 message ("Reference counted storage returned without modifying "
03246 "reference count: %s",
03247 exprNode_unparse (fexp)),
03248 loc);
03249 }
03250 }
03251 else if (iseitherassign)
03252 {
03253 if (alkind_isRefCounted (fkind))
03254 {
03255 if (!sRef_isLocalVar (tref))
03256 {
03257 vgenhinterror
03258 (FLG_REFCOUNTTRANS,
03259 message
03260 ("Assignment to non-local from reference counted storage: %s",
03261 exprNode_unparse (fexp)),
03262 cstring_makeLiteral
03263 ("Reference counted storage should call a function returning "
03264 "a newref instead of direct assignments."),
03265 loc);
03266 }
03267 else
03268 {
03269 ;
03270 }
03271 }
03272 }
03273 else
03274 {
03275 if (alkind_isRefCounted (tkind) || alkind_isTemp (tkind))
03276 {
03277
03278 }
03279 else if (alkind_isKillRef (tkind))
03280 {
03281 if (!ffix && !tfix && !(transferType == TT_FCNRETURN))
03282 {
03283 sRef_killComplete (fref, loc);
03284 }
03285 }
03286 else
03287 {
03288 if (!alkind_isError (tkind))
03289 {
03290 voptgenerror
03291 (FLG_REFCOUNTTRANS,
03292 message ("Reference counted storage %q: %q",
03293 transferErrorMessage (transferType, tkind),
03294 generateText (fexp, texp, tref, transferType)),
03295 loc);
03296 }
03297 }
03298 }
03299 }
03300 else
03301 {
03302 ;
03303 }
03304
03305 setCodePoint ();
03306
03307 if (alkind_isOnly (tkind) || alkind_isKeep (tkind))
03308 {
03309 if (sRef_isAddress (fref))
03310 {
03311 voptgenerror
03312 (FLG_IMMEDIATETRANS,
03313 message ("Immediate address %q %q: %q",
03314 sRef_unparse (fref),
03315 transferErrorMessage (transferType, tkind),
03316 generateText (fexp, texp, tref, transferType)),
03317 loc);
03318
03319 sRef_setAliasKind (fref, AK_ERROR, loc);
03320 }
03321 else
03322 {
03323 if ((alkind_isUnknown (fkind) || alkind_isStatic (fkind))
03324 && !sRef_isDefinitelyNull (fref)
03325 && (!ffix && !tfix)
03326 && (!exprNode_isNullValue (fexp)))
03327 {
03328 flagcode errkind = alkind_isStatic (fkind)
03329 ? FLG_STATICTRANS : FLG_UNKNOWNTRANS;
03330
03331 if (transferType == TT_GLOBINIT)
03332 {
03333 if (errkind == FLG_STATICTRANS)
03334 {
03335 errkind = FLG_STATICINITTRANS;
03336 }
03337 else
03338 {
03339 errkind = FLG_UNKNOWNINITTRANS;
03340 }
03341 }
03342
03343 if (optgenerror
03344 (errkind,
03345 message ("%s storage %s %q: %q",
03346 alkind_capName (fkind),
03347 exprNode_unparse (fexp),
03348 transferErrorMessage (transferType, tkind),
03349 generateText (fexp, texp, tref, transferType)),
03350 loc))
03351 {
03352 sRef_showAliasInfo (fref);
03353 }
03354 }
03355 }
03356
03357
03358 if (!alkind_isShared (fkind))
03359 {
03360 if (isassign)
03361 {
03362 if (!ffix)
03363 {
03364
03365
03366 if (!sRef_isNSLocalVar (tref) && !sRef_sameName (fref, tref))
03367 {
03368 if (!tfix)
03369 {
03370 sRef_setKeptComplete (fref, loc);
03371 }
03372 else
03373 {
03374 sRef_setKept (fref, loc);
03375 }
03376 }
03377 }
03378 }
03379 else
03380 {
03381 if (!ffix)
03382 {
03383 if (!tfix)
03384 {
03385 if (alkind_isKeep (tkind))
03386 {
03387 sRef_setKeptComplete (fref, loc);
03388 }
03389 else
03390 {
03391 sRef_killComplete (fref, loc);
03392 }
03393 }
03394 else
03395 {
03396 if (alkind_isKeep (tkind))
03397 {
03398 sRef_setKept (fref, loc);
03399 }
03400 else
03401 {
03402 sRef_kill (fref, loc);
03403 }
03404 }
03405 }
03406 }
03407 }
03408 }
03409 else if (alkind_isOwned (tkind))
03410 {
03411
03412 if (!alkind_isShared (fkind))
03413 {
03414 if (!isassign
03415 || !sRef_sameName (fref, tref))
03416 {
03417 if (!ffix)
03418 {
03419 if (!tfix)
03420 {
03421 sRef_setDependentComplete (fref, loc);
03422 }
03423 else
03424 {
03425 sRef_setDependent (fref, loc);
03426 }
03427 }
03428 }
03429 }
03430 }
03431 else if (alkind_isShared (tkind))
03432 {
03433 if (alkind_isFresh (fkind) || alkind_isLocal (fkind))
03434 {
03435 if (!ffix)
03436 {
03437 sRef_setShared (fref, loc);
03438 }
03439 }
03440 }
03441 else if (alkind_isUnknown (tkind) && context_getFlag (FLG_MEMIMPLICIT))
03442 {
03443 if (alkind_isDependent (fkind))
03444 {
03445 if (!exprNode_isNullValue (fexp)
03446 && ctype_isMutable (exprNode_getType (fexp))
03447 && (!iseitherassign || sRef_isReference (tref)))
03448 {
03449 if (canLoseReference (fref, loc))
03450 {
03451 ;
03452 }
03453 else
03454 {
03455 if (optgenerror
03456 (FLG_DEPENDENTTRANS,
03457 message ("%s storage %q%q: %q",
03458 alkind_capName (fkind),
03459 sRef_unparseOpt (fref),
03460 transferErrorMessage (transferType, tkind),
03461 generateText (fexp, texp, tref, transferType)),
03462 loc))
03463 {
03464 DPRINTF (("Here: %s / %s", sRef_unparseFull (fref),
03465 sRef_unparseFull (tref)));
03466 sRef_showAliasInfo (fref);
03467 }
03468 }
03469 }
03470 }
03471 }
03472 else if (alkind_isNewRef (tkind))
03473 {
03474 if (!ffix && !tfix)
03475 {
03476 sRef_killComplete (fref, loc);
03477 }
03478 }
03479 else if (alkind_isKillRef (tkind))
03480 {
03481 if (transferType == TT_FCNRETURN)
03482 {
03483 if (sRef_isNewRef (fref))
03484 {
03485 if (optgenerror
03486 (FLG_REFCOUNTTRANS,
03487 message ("New reference returned as temp reference: %q",
03488 generateText (fexp, texp, tref, transferType)),
03489 loc))
03490 {
03491 sRef_showAliasInfo (fref);
03492 }
03493 }
03494 }
03495 else
03496 {
03497 if (sRef_isNewRef (fref))
03498 {
03499 sRef_killComplete (fref, loc);
03500 }
03501 else
03502 {
03503 if (sRef_isRefCounted (fref)
03504 && sRef_isCvar (fref)
03505 && !sRef_isLocalVar (fref))
03506 {
03507 if (optgenerror
03508 (FLG_REFCOUNTTRANS,
03509 message
03510 ("External reference counted storage released: %q",
03511 generateText (fexp, texp, tref, transferType)),
03512 loc))
03513 {
03514 sRef_showAliasInfo (fref);
03515 }
03516 }
03517 }
03518 }
03519
03520 }
03521 else
03522 {
03523 ;
03524 }
03525
03526 setCodePoint ();
03527 }
03528
03529
03530
03531
03532
03533
03534
03535 static void
03536 checkTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref,
03537 fileloc loc, transferKind transferType)
03538 {
03539 setCodePoint ();
03540
03541 if (context_inProtectVars ())
03542 {
03543 return;
03544 }
03545
03546
03547
03548
03549
03550
03551 if (sRef_isLocalVar (tref) && transferType != TT_DOASSIGN)
03552 {
03553 sRefSet alias = usymtab_allAliases (tref);
03554
03555 sRefSet_realElements (alias, atref)
03556 {
03557 sRef abase = sRef_getRootBase (atref);
03558
03559 if (sRef_isKnown (atref)
03560 && !sRef_isLocalVar (abase)
03561 && !sRef_isExternal (abase))
03562 {
03563 atref = sRef_updateSref (atref);
03564
03565 if (sRef_hasName (atref))
03566 {
03567 if (!sRef_isNew (atref)
03568 && !sRef_sameName (tref, atref))
03569 {
03570 context_setAliasAnnote (atref, tref);
03571 }
03572
03573 checkTransferAux (fexp, fref, TRUE,
03574 texp, atref, FALSE,
03575 loc, transferType);
03576
03577 context_clearAliasAnnote ();
03578 }
03579 }
03580 } end_sRefSet_realElements;
03581
03582 sRefSet_free (alias);
03583 }
03584
03585
03586 if (sRef_isLocalVar (fref))
03587 {
03588 sRefSet alias = usymtab_allAliases (fref);
03589
03590 sRefSet_realElements (alias, afref)
03591 {
03592 sRef abase = sRef_getRootBase (afref);
03593
03594 if (sRef_isKnown (afref)
03595 && !sRef_isLocalVar (abase)
03596 && !sRef_isExternal (abase))
03597 {
03598 afref = sRef_updateSref (afref);
03599
03600 if (sRef_hasName (afref))
03601 {
03602 if (!sRef_isNew (afref)
03603 && !sRef_sameName (afref, fref))
03604 {
03605 context_setAliasAnnote (afref, fref);
03606 }
03607
03608 checkTransferAux (fexp, afref, FALSE,
03609 texp, tref, TRUE,
03610 loc, transferType);
03611
03612 context_clearAliasAnnote ();
03613 }
03614 }
03615 } end_sRefSet_realElements;
03616
03617 sRefSet_free (alias);
03618 }
03619
03620 setCodePoint ();
03621
03622 checkTransferAux (fexp, fref, FALSE, texp, tref, FALSE,
03623 loc, transferType);
03624
03625 setCodePoint ();
03626 }
03627
03628 static sRef
03629 dependentReference (sRef sr)
03630 {
03631 sRefSet ab = usymtab_aliasedBy (sr);
03632
03633
03634
03635
03636
03637
03638 if (!sRefSet_isEmpty (ab))
03639 {
03640 sRef res = sRef_undefined;
03641
03642
03643
03644
03645
03646
03647 sRefSet_realElements (ab, current)
03648 {
03649 if (sRef_isOwned (current))
03650 {
03651 res = current;
03652 break;
03653 }
03654 } end_sRefSet_realElements;
03655
03656 sRefSet_free (ab);
03657 return res;
03658 }
03659
03660 return sRef_undefined;
03661 }
03662
03663 bool canLoseReference (sRef sr, fileloc loc)
03664 {
03665 bool gotone = FALSE;
03666 sRefSet ab = usymtab_aliasedBy (sr);
03667
03668
03669
03670
03671
03672
03673
03674 if (!sRefSet_isEmpty (ab))
03675 {
03676
03677
03678
03679
03680
03681 sRefSet_realElements (ab, current)
03682 {
03683 sRef_setLastReference (current, sr, loc);
03684 gotone = TRUE;
03685 break;
03686 } end_sRefSet_realElements;
03687
03688 sRefSet_free (ab);
03689 }
03690
03691 return gotone;
03692 }
03693
03694 bool canLoseLocalReference (sRef sr, fileloc loc)
03695 {
03696 bool gotone = FALSE;
03697 sRefSet ab = usymtab_aliasedBy (sr);
03698
03699
03700
03701
03702
03703
03704
03705 if (!sRefSet_isEmpty (ab))
03706 {
03707
03708
03709
03710
03711
03712 sRefSet_realElements (ab, current)
03713 {
03714 if (sRef_isRealLocalVar (sRef_getRootBase (current)))
03715 {
03716 sRef_setLastReference (current, sr, loc);
03717 gotone = TRUE;
03718 break;
03719 }
03720 } end_sRefSet_realElements;
03721
03722 sRefSet_free (ab);
03723 }
03724
03725 return gotone;
03726 }
03727
03728