Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

aliasChecks.c

Go to the documentation of this file.
00001 /*
00002 ** LCLint - annotation-assisted static program checker
00003 ** Copyright (C) 1994-2000 University of Virginia,
00004 **         Massachusetts Institute of Technology
00005 **
00006 ** This program is free software; you can redistribute it and/or modify it
00007 ** under the terms of the GNU General Public License as published by the
00008 ** Free Software Foundation; either version 2 of the License, or (at your
00009 ** option) any later version.
00010 ** 
00011 ** This program is distributed in the hope that it will be useful, but
00012 ** WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** General Public License for more details.
00015 ** 
00016 ** The GNU General Public License is available from http://www.gnu.org/ or
00017 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018 ** MA 02111-1307, USA.
00019 **
00020 ** For information on lclint: lclint-request@cs.virginia.edu
00021 ** To report a bug: lclint-bug@cs.virginia.edu
00022 ** For more information: http://lclint.cs.virginia.edu
00023 */
00024 /*
00025 ** aliasChecks.c
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 /*@exposed@*/ sRef dependentReference (sRef p_sr);
00048 static bool canLoseLocalReference (sRef p_sr, fileloc p_loc) ;
00049 
00050 /*
00051 ** returns the most specific alkind
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 ** tref <- fref
00064 **
00065 ** transferType:
00066 **   FCNRETURN   return fref; tref is return type
00067 **   GLOBASSIGN  tref = fref; 
00068 **   FCNPASS     call (fref) ; tref is the argument type
00069 **
00070 */
00071 
00072 static /*@only@*/ 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 /*@observer@*/ 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 /*@dependent@*/ 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 /*@observer@*/ 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 /*@observer@*/ 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 /*@only@*/ 
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 ** returns TRUE if fref is completely defined.
00249 ** if !report, returns TRUE unless error is at the deep level.
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               /* no error */
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               ; /* no error (will be a definition error) */
00346             }
00347           else if (transferType == TT_DOASSIGN
00348                    || transferType == TT_FIELDASSIGN
00349                    || transferType == TT_GLOBINIT
00350                    || transferType == TT_FCNPASS)
00351             {
00352               ; /* no error */
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               ; /* no error (will be a definition error) */
00444             }
00445           else if (transferType == TT_DOASSIGN)
00446             {
00447               ; /* no error */
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       /* should check fref is allocated? */
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               ** for structures, each field must be completely defined
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                   /* no error */
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               ** for unions, at least one field must be completely defined
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                           ; /* no error */
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 ** fref is being free'd
01165 */
01166 
01167 typedef enum {
01168   DSC_GLOB, DSC_LOCAL, DSC_PARAM, DSC_STRUCT
01169   } dscCode;
01170 
01171 static /*@observer@*/ 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); /* prevent further errors */
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           ** Bogosity necessary to prevent infinite depth.
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       ** for structures, each field must be completely destroyed
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               ** note order of && operands --- want to report multiple errors
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                   ** Non-results are checked in exit scope.
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               ; /* nothing to check before */
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 ** should not modify arg
01562 */
01563 
01564 void
01565 checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
01566                    /*@dependent@*/ 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       /* make it defined now, so checkTransfer is okay */
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               /* yes, I really mean this! */
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   /* need to fixup here: derived refs could be bogus */
01843   /* (better to change sRef to not add derivs for "protected" ref) */
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       /* caller cannot use, nothing to check */
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 ** For lhs of assignment, alias kind is set from basic type.
01913 ** Yoikes!
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       /* constants can match anything (e.g., NULL) */
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, /*@unused@*/ bool ffix,
02067                       sRef tref, exprNode texp, /*@unused@*/ 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   ** check for null (don't need to check aliases??)
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, /*@unused@*/ bool ffix,
02146                         sRef tref, exprNode texp, bool tfix,
02147                         fileloc loc, transferKind transferType)
02148 {
02149   alkind tkind = sRef_getAliasKind (tref);
02150 
02151   /*
02152   ** Assignment to same --- no errors, or state changes.
02153   ** This can happen when returned params are used.
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)) /* okay to assign to self (returned params) */
02172       && !(usymtab_isProbableNull (tref))) 
02173     {
02174       if (context_getFlag (FLG_MUSTFREE))
02175         {
02176           if (canLoseReference (tref, loc))
02177             {
02178               ; /* no error */
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                       /* no errors for static initializations */
02202                     }
02203                   else 
02204                     {
02205                       /*
02206                        ** don't report this error for a[i], since it could
02207                        ** be a new element.
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)) /* tkind might not be correct now */
02256     {
02257       if (sRef_isNewRef (fref))
02258         {
02259           sRef_setAliasKind (tref, AK_NEWREF, loc);
02260         }
02261       else if (sRef_isConst (fref))
02262         {
02263           /* for now, constants are not ref counted */
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   ** Not for structures and unions, since assignments copy.
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) /*< should only apply to static >*/
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 ** requires sRef_isOnly (fref)
02310 */
02311 
02312 static void
02313 checkOnlyTransferAux (sRef fref, exprNode fexp, bool ffix,
02314                       sRef tref, exprNode texp, /*@unused@*/ 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       /* no errors for exposed transfers (is this good enough?) */
02337     }
02338   else if (alkind_isOnly (tkind) || alkind_isKeep (tkind) || alkind_isOwned (tkind))
02339     {
02340       ; /* okay */
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                   ; /* don't set this --- corresponds to return transfer */
02390                 }
02391               else
02392                 {
02393                   /*
02394                   ** Don't set local to dependent.  Error will
02395                   ** be detected through aliasing.  Except for
02396                   ** arrays.
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               ; /* okay */
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           ** alias kind unknown to suppress future messages
02455           */
02456           
02457           if (!ffix && sRef_isNSLocalVar (sRef_getRootBase (fref)))
02458             {
02459               sRef_clearAliasKind (fref);
02460             }
02461         }
02462     }
02463 }
02464 
02465 /*
02466 ** ??? same as checkOnly ?
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       /* okay */
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               ; /* okay */
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            ** alias kind unknown to suppress future messages
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, /*@unused@*/ bool tfix,
02561                        fileloc loc, transferKind transferType)
02562 {     
02563   alkind tkind = sRef_getAliasKind (tref);
02564 
02565   /*
02566   ** error to return fresh as non-only
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   ** Okay to assign fresh to only, shared or unqualified.
02616   ** 
02617   ** should generate other errors? 
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           ** local shares fresh.  Make it owned/dependent. 
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           /* NO! sRef_clearAliasKind (fref); */
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, /*@unused@*/ 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       ** observer -> exposed or observer
02724       */
02725       
02726       /*
02727       ** observer -> temp is okay [NO!  really? only in function calls]
02728       */
02729 
02730       if (sRef_isExposed (tref) || sRef_isObserver (tref)
02731           || alkind_isLocal (tkind))
02732         {
02733           /* okay */
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                       ; /* No error for local assignment or assignment
02771                            to static array (copies string). */
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                       /* sRef_setAliasKind (tref, AK_ERROR, loc); */
02816                     }
02817                 }
02818             }
02819           else /* TT_FCNPASS */
02820             {
02821               llassert (transferType == TT_FCNPASS);
02822 
02823               if (alkind_isTemp (tkind) 
02824                   || alkind_isDependent (tkind)
02825                   || alkind_isRefCounted (tkind))
02826                 {
02827                   ; /* okay */
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 ** returns TRUE if there is no error reported
02943 **
02944 ** if fixt, don't change tref (except if error reported.)
02945 ** if fixf, don't change fref (except if error reported.)
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   ** Check for definition 
02979   */
02980 
02981   /*
02982   ** errors passing out params already detected in checkAnyCall
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   ** check exposure
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   ** check aliasing
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           ; /* okay */
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       ** xxx <- shared
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       ** xxx <- temp
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           ** check that the refs field has been modified
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 /* fcnpass */
03274         {
03275           if (alkind_isRefCounted (tkind) || alkind_isTemp (tkind))
03276             {
03277               /* okay --- no change in state */
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       /* don't kill shared to suppress future messages */
03358       if (!alkind_isShared (fkind))
03359         {
03360           if (isassign)
03361             {
03362               if (!ffix) 
03363                 {
03364                   /*< yuk! should do this in aliasaux >*/
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       /* don't kill shared to suppress future messages */
03412       if (!alkind_isShared (fkind)) 
03413         {
03414           if (!isassign 
03415               || !sRef_sameName (fref, tref)) /* result of return parameter */
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 ** assigns fexp := tref or passes fexp as a parameter, or returns fexp.
03531 **
03532 ** For assignments, sets alias and definition state accordingly.
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   ** for local references, we need to check
03548   ** the transfer for all possible aliases.
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 /*@exposed@*/ sRef 
03629   dependentReference (sRef sr)
03630 {
03631   sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
03632   
03633   /*
03634   ** If there is a local variable that aliases sr, then there is no
03635   ** error.  Make the local an only.
03636   */
03637   
03638   if (!sRefSet_isEmpty (ab))
03639     {
03640       sRef res = sRef_undefined;
03641 
03642       /*
03643       ** make one an only, others alias it
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); /* yes, really mean aliasedBy */
03667   
03668     
03669   /*
03670    ** if there is a local variable that aliases sr, then there is no
03671    ** error.  Make the local an only.
03672    */
03673   
03674   if (!sRefSet_isEmpty (ab))
03675     {
03676       /*
03677       ** make one an only, others alias it
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); /* yes, really mean aliasedBy */
03698   
03699     
03700   /*
03701    ** if there is a local variable that aliases sr, then there is no
03702    ** error.  Make the local an only.
03703    */
03704   
03705   if (!sRefSet_isEmpty (ab))
03706     {
03707       /*
03708       ** make one an only, others alias it
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 

Generated at Fri Nov 3 18:57:38 2000 for LCLint by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000