]> andersk Git - splint.git/blob - src/transferChecks.c
fe12682be7a5c64cbce70f74842edde0cffc77e1
[splint.git] / src / transferChecks.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 ** 
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** General Public License for more details.
15 ** 
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
19 **
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** transferChecks.c
26 */
27
28 # include "splintMacros.nf"
29 # include "basic.h"
30 # include "transferChecks.h"
31
32 /* transfer types: */
33 typedef enum
34 {
35   TT_FCNRETURN,
36   TT_DOASSIGN,
37   TT_FIELDASSIGN,
38   TT_FCNPASS,
39   TT_GLOBPASS,
40   TT_GLOBRETURN,
41   TT_PARAMRETURN,
42   TT_LEAVETRANS,
43   TT_GLOBINIT
44 } transferKind;
45
46 static void checkStructTransfer (exprNode p_lhs, sRef p_slhs, exprNode p_rhs, sRef p_srhs,
47                                  fileloc p_loc, transferKind p_tt);
48 static void checkMetaStateConsistent (/*@exposed@*/ sRef p_fref, sRef p_tref, 
49                                       fileloc p_loc, transferKind p_transferType) ;
50
51 static void checkLeaveTrans (uentry p_actual, transferKind p_transferType);
52 static void checkTransfer (exprNode p_fexp, /*@dependent@*/ sRef p_fref,
53                            exprNode p_texp, /*@dependent@*/ sRef p_tref, 
54                            exprNode p_fcn, /* for printing better error messages */
55                            fileloc p_loc, transferKind p_transferType);
56 static void checkGlobTrans (uentry p_glob, transferKind p_type);
57
58 static ynm
59 checkCompletelyDefined (exprNode p_fexp, /*@exposed@*/ sRef p_fref, sRef p_ofref,
60                         exprNode p_texp, sRef p_tref,
61                         bool p_topLevel, bool p_inUnion, bool p_directUnion,
62                         fileloc p_loc, transferKind p_transferType, int p_depth,
63                         bool p_report);
64
65 static /*@exposed@*/ sRef dependentReference (sRef p_sr);
66 static bool canLoseLocalReference (/*@dependent@*/ sRef p_sr, fileloc p_loc) ;
67
68 /*
69 ** returns the most specific alkind
70 */
71
72 alkind alkind_resolve (alkind a1, alkind a2)
73 {
74   if (a1 == AK_UNKNOWN || a1 == AK_ERROR) return a2;
75   if (a2 == AK_UNKNOWN || a2 == AK_ERROR || a2 == AK_LOCAL) return a1;
76   if (a1 == AK_LOCAL) return a2;
77   return a1;
78 }
79
80 /*
81 ** tref <- fref
82 **
83 ** transferType:
84 **   FCNRETURN   return fref; tref is return type
85 **   GLOBASSIGN  tref = fref; 
86 **   FCNPASS     call (fref) ; tref is the argument type
87 **
88 */
89
90 static /*@only@*/ cstring
91 transferErrorMessage (transferKind transferType, alkind tkind) /*@*/ 
92 {
93   switch (transferType)
94     {
95     case TT_FCNRETURN:
96       return (message ("returned as %s", alkind_unparse (tkind)));
97     case TT_DOASSIGN:
98       return (message ("assigned to %s", alkind_unparse (tkind)));
99     case TT_FIELDASSIGN:
100       return (message ("assigned to %s", alkind_unparse (tkind)));
101     case TT_GLOBINIT:
102       return (message ("used as initial value for %s", 
103                        alkind_unparse (tkind)));
104     case TT_FCNPASS:
105       return (message ("passed as %s param", alkind_unparse (tkind)));
106     BADDEFAULT;
107     }
108   BADEXIT;
109 }
110
111 static /*@only@*/ cstring
112 transferErrorExcerpt (transferKind transferType, exprNode fexp, exprNode texp, exprNode fcn) /*@*/ 
113 {
114   switch (transferType)
115     {
116     case TT_FCNRETURN:
117       return (message ("return %s", exprNode_unparse (fexp)));
118     case TT_FIELDASSIGN:
119     case TT_DOASSIGN:
120     case TT_GLOBINIT:
121       return (message ("%s = %s", exprNode_unparse (texp), exprNode_unparse (fexp)));
122     case TT_FCNPASS:
123       if (exprNode_isDefined (fcn))
124         {
125           return message ("%s(..., %s, ...)",
126                           exprNode_unparse (fcn),
127                           exprNode_unparse (fexp));
128         }
129       else
130         {
131           return cstring_copy (exprNode_unparse (fexp));  
132         }
133     BADDEFAULT;
134     }
135   BADEXIT;
136 }
137
138 static cstring
139 transferErrorExpMessage (transferKind transferType, exkind tkind) /*@*/
140 {
141   if (exkind_isUnknown (tkind))
142     {
143       switch (transferType)
144         {
145         case TT_FCNRETURN:
146           return (cstring_makeLiteral ("returned without qualification"));
147         case TT_FIELDASSIGN:
148         case TT_DOASSIGN:
149           return (cstring_makeLiteral ("assigned to unqualified reference"));
150         case TT_FCNPASS:
151           return (cstring_makeLiteral ("passed without qualification"));
152         case TT_GLOBINIT:
153           return (cstring_makeLiteral ("used as initial value for unqualified storage"));
154         BADDEFAULT;
155         }
156     }
157   else
158     {
159       switch (transferType)
160         {
161         case TT_FCNRETURN:
162           return (message ("returned as %s", exkind_unparse (tkind)));
163         case TT_FIELDASSIGN:
164         case TT_DOASSIGN:
165           return (message ("assigned to %s", exkind_unparse (tkind)));
166         case TT_FCNPASS:
167           return (message ("passed as %s param", exkind_unparse (tkind)));
168           BADDEFAULT;
169         }
170     }
171
172   BADEXIT;
173 }
174
175 static /*@observer@*/ cstring
176 transferNullMessage (transferKind transferType) /*@*/
177 {
178   switch (transferType)
179     {
180     case TT_FCNRETURN:
181       return (cstring_makeLiteralTemp ("returned as non-null"));
182     case TT_DOASSIGN:
183     case TT_FIELDASSIGN:
184       return (cstring_makeLiteralTemp ("assigned to non-null"));
185     case TT_GLOBINIT:
186       return (cstring_makeLiteralTemp ("initialized to non-null"));
187     case TT_FCNPASS:
188       return (cstring_makeLiteralTemp ("passed as non-null param"));
189     BADDEFAULT;
190     }
191   BADEXIT;
192 }
193
194 static /*@dependent@*/ exprNode atFunction = exprNode_undefined;
195 static int atArgNo = 0;
196 static int atNumArgs = 0;
197
198 static cstring generateText (exprNode e1, exprNode e2, 
199                              sRef tref, transferKind tt) 
200    /*@*/
201 {
202   if (tt == TT_DOASSIGN || tt == TT_GLOBINIT)
203     {
204       return (message ("%s = %s", exprNode_unparse (e2),
205                        exprNode_unparse (e1)));
206     }
207   else if (tt == TT_FIELDASSIGN)
208     {
209       return (message ("%s = %s (field %q)",
210                        exprNode_unparse (e2),
211                        exprNode_unparse (e1),
212                        sRef_unparse (tref)));
213     }
214   else if (tt == TT_FCNPASS)
215     {
216       return (message ("%s (%s%s%s)",
217                        exprNode_unparse (atFunction),
218                        (atArgNo == 1 ? cstring_undefined 
219                 : cstring_makeLiteralTemp ("..., ")),
220                        exprNode_unparse (e1),
221                        (atArgNo == atNumArgs ? cstring_undefined
222                         : cstring_makeLiteralTemp (", ..."))));
223     }
224   else
225     {
226       return (cstring_copy (exprNode_unparse (e1)));
227     }
228 }
229
230 static /*@observer@*/ cstring
231 transferType_unparse (transferKind transferType) /*@*/
232 {
233   switch (transferType)
234     {
235     case TT_FCNRETURN:
236       return (cstring_makeLiteralTemp ("Returned"));
237     case TT_DOASSIGN:
238     case TT_FIELDASSIGN:
239       return (cstring_makeLiteralTemp ("Assigned"));
240     case TT_FCNPASS:
241       return (cstring_makeLiteralTemp ("Passed"));
242     case TT_GLOBINIT:
243       return (cstring_makeLiteralTemp ("Initialized"));
244     case TT_GLOBRETURN:
245       return (cstring_makeLiteralTemp ("GLOB RETURN!"));
246     case TT_GLOBPASS:
247       return (cstring_makeLiteralTemp ("GLOB PASS!"));
248     case TT_PARAMRETURN:
249       return (cstring_makeLiteralTemp ("PARAM RETURN!"));
250     case TT_LEAVETRANS:
251       return (cstring_makeLiteralTemp ("LEAVE TRANS!"));
252     BADDEFAULT;
253     }
254   BADEXIT;
255 }
256
257 static /*@observer@*/ cstring udError (sRef s)
258 {
259   if (sRef_isDead (s))
260     {
261       return cstring_makeLiteralTemp ("released");
262     }
263   else if (sRef_isAllocated (s))
264     {
265       return cstring_makeLiteralTemp ("allocated but not defined");
266     }
267   else
268     {
269       return cstring_makeLiteralTemp ("undefined");
270     }
271 }
272
273 static /*@only@*/ 
274 cstring defExpl (sRef s) /*@*/
275 {
276   sRef rb = sRef_getRootBase (s);
277
278   if (sRef_sameName (rb, s))
279     {
280       if (sRef_isAllocated (s))
281         {
282           return cstring_makeLiteral (" (allocated only)");
283         }
284       return cstring_undefined;
285     }
286   else
287     {
288       return (message (" (%q is %s)", sRef_unparse (s), udError (s)));
289     }
290 }
291
292 /*
293 **
294 ** More than just definition checking --- checks for consistent state also!
295 **
296 ** Returns TRUE if fref is completely defined.
297 ** if !report, returns TRUE unless error is at the deep level.
298 */
299
300 static ynm
301 checkCompletelyDefined (exprNode fexp, /*@exposed@*/ sRef fref, sRef ofref,
302                         exprNode texp, sRef tref, 
303                         bool topLevel, bool inUnion, bool directUnion,
304                         fileloc loc, transferKind transferType,
305                         int depth, bool report)
306 {
307   ctype ct;
308   alkind fkind = sRef_getAliasKind (fref);
309   alkind tkind = sRef_getAliasKind (tref);
310   
311   DPRINTF (("Check completely defined: %s [%s] / %s [%s]",
312             exprNode_unparse (fexp), sRef_unparseFull (fref),
313             exprNode_unparse (texp), sRef_unparseFull (tref)));
314
315   if (depth > MAXDEPTH)
316     {
317       llquietbug
318         (message 
319          ("Check definition limit exceeded, checking %q. "
320           "This either means there is a variable with at least "
321           "%d indirections apparent in the program text, or "
322           "there is a bug in Splint.",
323           sRef_unparse (fref),
324           MAXDEPTH));
325
326       return YES;
327     }
328
329   if (!sRef_isKnown (fref))
330     {
331       return YES;
332     }
333
334   if (sRef_isDead (fref))
335     {
336       DPRINTF (("Dead storage to completely defined: %s", sRef_unparseFull (fref)));
337     }
338
339   if (alkind_isStack (fkind))
340     {
341       ctype rt = ctype_realType (sRef_getType (tref));
342
343       if (ctype_isMutable (rt) && !ctype_isSU (rt))
344         {
345           if (transferType == TT_PARAMRETURN)
346             {
347               if (optgenerror 
348                   (FLG_RETSTACK,
349                    message
350                    ("Stack-allocated storage %qreachable from parameter %q",
351                     sRef_unparseOpt (fref),
352                     sRef_unparse (ofref)),
353                    loc))
354                 {
355                   sRef_showAliasInfo (fref);
356                 }
357             }
358           else if (transferType == TT_GLOBRETURN)
359             {
360               if (optgenerror 
361                   (FLG_RETSTACK,
362                    message
363                    ("Stack-allocated storage %qreachable from global %q",
364                     sRef_unparseOpt (fref),
365                     sRef_unparse (ofref)),
366                    loc))
367                 {
368                   sRef_showAliasInfo (fref);
369                 }
370             }
371           else if (transferType == TT_FCNRETURN)
372             {
373               if (optgenerror 
374                   (FLG_RETSTACK,
375                    message 
376                    ("Stack-allocated storage %qreachable from return value: %s",
377                     sRef_unparseOpt (fref), 
378                     exprNode_unparse (fexp)),
379                    loc))
380                 {
381                   sRef_showAliasInfo (fref);
382                 }
383             }
384           else
385             {
386               /* no error */
387             }
388         }
389     }
390
391   if (!topLevel)
392     {
393       DPRINTF (("From: %s ==> %s",
394                 sRef_unparseFull (fref),
395                 sRef_unparseFull (tref)));
396       
397       checkMetaStateConsistent (fref, tref, loc, transferType);
398
399       if ((sRef_isObserver (fref) && !sRef_isObserver (tref))
400           || (sRef_isExposed (fref) && !(sRef_isObserver (tref) 
401                                          || sRef_isExposed (tref))))
402         {
403           flagcode code = (sRef_isObserver (fref) 
404                            ? FLG_OBSERVERTRANS : FLG_EXPOSETRANS);
405
406           if (!sRef_isStateLive (fref))
407             {
408               ; /* no error (will be a definition error) */
409             }
410           else if (transferType == TT_DOASSIGN
411                    || transferType == TT_FIELDASSIGN
412                    || transferType == TT_GLOBINIT
413                    || transferType == TT_FCNPASS)
414             {
415               ; /* no error */
416             }
417           else if (transferType == TT_PARAMRETURN)
418             {
419               if (optgenerror 
420                   (code,
421                    message
422                    ("%s storage %qreachable from %s parameter",
423                     exkind_capName (sRef_getExKind (fref)),
424                     sRef_unparseOpt (fref), 
425                     exkind_unparseError (sRef_getExKind (tref))),
426                    loc))
427                 {
428                   sRef_showExpInfo (fref);
429                   sRef_setExKind (fref, XO_UNKNOWN, loc);
430                 }
431             }
432           else if (transferType == TT_LEAVETRANS)
433             {
434               ;
435             }
436           else if (transferType == TT_GLOBINIT)
437             {
438               if (optgenerror 
439                   (code,
440                    message 
441                    ("%s storage %qreachable from %s initial value",
442                     exkind_capName (sRef_getExKind (fref)),
443                     sRef_unparseOpt (fref), 
444                     exkind_unparseError (sRef_getExKind (tref))),
445                    loc))
446                 {
447                   sRef_showExpInfo (fref);
448                   sRef_setExKind (fref, XO_UNKNOWN, loc);
449                 }
450             }
451           else if (transferType == TT_GLOBRETURN)
452             {
453               if (optgenerror 
454                   (code,
455                    message
456                    ("%s storage %qreachable from %s global",
457                     exkind_capName (sRef_getExKind (fref)),
458                     sRef_unparseOpt (fref), 
459                     exkind_unparseError (sRef_getExKind (tref))),
460                    loc))
461                 {
462                   sRef_showExpInfo (fref);
463                   sRef_setExKind (fref, XO_UNKNOWN, loc);
464                 }
465             }
466           else if (transferType == TT_FCNRETURN)
467             {
468               if (optgenerror 
469                   (code,
470                    message 
471                    ("%s storage %qreachable from %s return value",
472                     exkind_capName (sRef_getExKind (fref)),
473                     sRef_unparseOpt (fref), 
474                     exkind_unparseError (sRef_getExKind (tref))),
475                    loc))
476                 {
477                   sRef_showExpInfo (fref);
478                   sRef_setExKind (fref, XO_UNKNOWN, loc);
479                 }
480             }
481           else
482             {
483               llcontbug (message ("Transfer type: %s", 
484                                   transferType_unparse (transferType)));
485               
486               if (optgenerror 
487                   (code,
488                    message
489                    ("%s storage %qreachable from %s return value",
490                     exkind_capName (sRef_getExKind (fref)),
491                     sRef_unparseOpt (fref), 
492                     exkind_unparseError (sRef_getExKind (tref))),
493                    loc))
494                 {
495                   sRef_showExpInfo (fref);
496                   sRef_setExKind (fref, XO_UNKNOWN, loc);
497                 }
498             }
499
500         }
501       
502       if (!alkind_compatible (fkind, tkind))
503         {
504           if (fkind == AK_UNKNOWN && !sRef_isStateLive (fref))
505             {
506               ; /* no error (will be a definition error) */
507             }
508           else if (transferType == TT_DOASSIGN
509                    || transferType == TT_FIELDASSIGN) /* evans 2002-02-05 - added TT_FIELDASSIGN */
510             {
511               ; /* no error */
512             }
513           else if (transferType == TT_FCNPASS)
514             {
515               if (alkind_isKnown (sRef_getAliasKind (tref)))
516                 {
517                   if (optgenerror 
518                       (FLG_COMPMEMPASS,
519                        message
520                        ("Storage %qreachable from passed parameter "
521                         "is %s (should be %s): %s",
522                         sRef_unparseOpt (fref), 
523                         alkind_unparse (sRef_getAliasKind (fref)),
524                         alkind_unparse (sRef_getAliasKind (tref)),
525                         exprNode_unparse (fexp)),
526                        loc))
527                     {
528                       sRef_showAliasInfo (fref);
529                     }
530                 }
531             }
532           else if (transferType == TT_PARAMRETURN)
533             {
534               bool noerror = FALSE;
535
536               if (alkind_isDependent (sRef_getAliasKind (fref)))
537                 {
538                   if (canLoseLocalReference (fref, loc))
539                     {
540                       noerror = TRUE;
541                     }
542                 }
543
544               if (!noerror
545                   && optgenerror 
546                   (FLG_COMPMEMPASS,
547                    message
548                    ("Storage %qreachable from parameter is %s (should be %s)",
549                     sRef_unparseOpt (fref), 
550                     alkind_unparse (sRef_getAliasKind (fref)),
551                     alkind_unparse (sRef_getAliasKind (tref))),
552                    loc))
553                 {
554                   sRef_showAliasInfo (fref);
555                 }
556               }
557           else if (transferType == TT_LEAVETRANS)
558             {
559               if (optgenerror 
560                   (FLG_COMPMEMPASS,
561                    message
562                    ("Storage %qreachable from temporary reference is %s "
563                     "at scope exit (should be %s)",
564                     sRef_unparseOpt (fref), 
565                     alkind_unparse (sRef_getAliasKind (fref)),
566                     alkind_unparse (sRef_getAliasKind (tref))),
567                    loc))
568                 {
569                   sRef_showAliasInfo (fref);
570                 }
571               }
572           else if (transferType == TT_GLOBRETURN)
573             {
574               if (optgenerror 
575                   (FLG_COMPMEMPASS,
576                    message
577                    ("Storage %qreachable from global is %s (should be %s)",
578                     sRef_unparseOpt (fref), 
579                     alkind_unparse (sRef_getAliasKind (fref)),
580                     alkind_unparse (sRef_getAliasKind (tref))),
581                    loc))
582                 {
583                   sRef_showAliasInfo (fref);
584                 }
585             }
586           else if (transferType == TT_FCNRETURN)
587             {
588               if (optgenerror 
589                   (FLG_COMPMEMPASS,
590                    message 
591                    ("Storage %qreachable from return value is %s (should be %s)",
592                     sRef_unparseOpt (fref), 
593                     alkind_unparse (sRef_getAliasKind (fref)),
594                     alkind_unparse (sRef_getAliasKind (tref))),
595                    loc))
596                 {
597                   sRef_showAliasInfo (fref);
598                 }
599             }
600           else if (transferType == TT_GLOBINIT)
601             {
602               if (optgenerror 
603                   (FLG_COMPMEMPASS,
604                    message 
605                    ("Storage %qreachable from initial value is %s (should be %s)",
606                     sRef_unparseOpt (fref), 
607                     alkind_unparse (sRef_getAliasKind (fref)),
608                     alkind_unparse (sRef_getAliasKind (tref))),
609                    loc))
610                 {
611                   sRef_showAliasInfo (fref);
612                 }
613             }
614           else
615             {
616               llcontbug (message ("Transfer type: %s", 
617                                   transferType_unparse (transferType)));
618               
619               if (optgenerror 
620                   (FLG_COMPMEMPASS,
621                    message
622                    ("Storage %qreachable from return value is %s (should be %s)",
623                     sRef_unparseOpt (fref), 
624                     alkind_unparse (sRef_getAliasKind (fref)),
625                     alkind_unparse (sRef_getAliasKind (tref))),
626                    loc))
627                 {
628                   sRef_showAliasInfo (fref);
629                 }
630             }
631         }
632
633       if (sRef_isDead (fref))
634         {
635           if (directUnion)
636             {
637               return NO;
638             }
639
640           if (transferType == TT_PARAMRETURN)
641             {
642               if (optgenerror 
643                   (FLG_USERELEASED,
644                    message 
645                    ("Released storage %q reachable from parameter at return point",
646                     sRef_unparse (fref)),
647                    loc))
648                 {
649                   sRef_showStateInfo (fref);
650                   return YES;
651                 }
652               }
653           else if (transferType == TT_LEAVETRANS)
654             {
655               if (optgenerror 
656                   (FLG_USERELEASED,
657                    message ("Released storage %q reachable from temporary "
658                             "reference at scope exit",
659                             sRef_unparse (fref)),
660                    loc))
661                 {
662                   sRef_showStateInfo (fref);
663                   return YES;
664                 }
665               }
666           else if (transferType == TT_GLOBRETURN)
667             {
668               if (optgenerror 
669                   (FLG_GLOBSTATE,
670                    message ("Released storage %q reachable from global",
671                             sRef_unparse (fref)),
672                    loc))
673                 {
674                   sRef_showStateInfo (fref);
675                   return YES;
676                 }
677             }
678           else if (transferType == TT_FCNPASS)
679             {
680               if (optgenerror 
681                   (FLG_USERELEASED,
682                    message ("Released storage %q reachable from passed parameter",
683                             sRef_unparse (fref)),
684                    loc))
685                 {
686                   sRef_showStateInfo (fref);
687                   return YES;
688                 }
689             }
690           else
691             {
692               if (optgenerror 
693                   (FLG_USERELEASED,
694                    message ("Released storage %q reachable from parameter",
695                             sRef_unparse (fref)),
696                    loc))
697                 {
698                   sRef_showStateInfo (fref);
699                   return YES;
700                 }
701             }
702         }
703     }
704
705   if (!topLevel 
706       && sRef_possiblyNull (fref) 
707       && !sRef_perhapsNull (tref) 
708       && ctype_isRealPointer (sRef_getType (tref))
709       && !usymtab_isGuarded (fref))
710     {
711       if (transferType == TT_FCNRETURN)
712         {
713           if (optgenerror 
714               (FLG_NULLRET, 
715                message ("%q storage %qderivable from return value: %s", 
716                         cstring_capitalize (sRef_nullMessage (fref)),
717                         sRef_unparseOpt (fref),
718                         exprNode_unparse (fexp)),
719                loc))
720             {
721               sRef_showNullInfo (fref);
722
723               DPRINTF (("fref: %s", sRef_unparseFull (fref)));
724               DPRINTF (("tref: %s", sRef_unparseFull (tref)));
725
726               sRef_setNullError (fref);
727             }
728         }
729       else if (transferType == TT_GLOBRETURN || transferType == TT_PARAMRETURN)
730         {
731           if (optgenerror 
732               (FLG_NULLSTATE,
733                message 
734                ("Function returns with %s storage derivable from %q %q", 
735                 sRef_nullMessage (fref),
736                 cstring_makeLiteral ((transferType == TT_GLOBRETURN) 
737                                      ? "global" : "parameter"),
738                 sRef_unparse (fref)),
739                loc))
740             {
741               sRef_showNullInfo (fref);
742               sRef_setNullError (fref);
743             }
744         }
745       else if (transferType == TT_GLOBPASS)
746         {
747           if (optgenerror
748               (FLG_NULLPASS,
749                message ("Function called with %s storage "
750                         "derivable from global %q", 
751                         sRef_nullMessage (fref),
752                         sRef_unparse (fref)),
753                loc))
754             {
755               sRef_showNullInfo (fref);
756               sRef_setNullError (fref);
757             }
758         }
759       else if (transferType == TT_FCNPASS)
760         {
761           if (optgenerror
762               (FLG_NULLSTATE,
763                message ("%q storage %qderivable from parameter %q", 
764                         cstring_capitalize (sRef_nullMessage (fref)),
765                         sRef_unparseOpt (fref),
766                         generateText (fexp, exprNode_undefined, 
767                                       sRef_undefined, TT_FCNPASS)),
768                loc))
769             {
770               DPRINTF (("fref: %s", sRef_unparseFull (fref)));
771               DPRINTF (("tref: %s", sRef_unparseFull (tref)));
772               sRef_showNullInfo (fref);
773               sRef_setNullError (fref);
774             }
775         }
776       else
777         {
778           llassert (transferType == TT_DOASSIGN
779                     || transferType == TT_FIELDASSIGN /* evans 2002-02-05: no warnings for local fields */
780                     || transferType == TT_GLOBINIT
781                     || transferType == TT_LEAVETRANS);
782         }
783     }
784
785   if (sRef_isRelDef (tref) 
786       || sRef_isPartial (tref) 
787       || sRef_isAllocated (tref)
788       || sRef_isStateSpecial (tref))
789     {
790       /* should check fref is allocated? */
791       return YES;
792     }
793
794   ct = ctype_realType (sRef_getType (fref));
795
796   DPRINTF (("Here: %s", ctype_unparse (ct)));
797
798   if (!(sRef_isAnyDefined (fref) 
799         || sRef_isPdefined (fref)
800         || sRef_isAllocated (fref)
801         || sRef_isStateUnknown (fref)))
802     {
803       if (transferType == TT_GLOBRETURN)
804         {
805           if (report
806               && optgenerror 
807               (FLG_COMPDEF,
808                message ("Function returns with global %q not "
809                         "completely defined%q",
810                         sRef_unparse (sRef_getRootBase (fref)),
811                         defExpl (fref)),
812                loc))
813             {
814               sRef_showStateInfo (fref);
815               sRef_setDefined (fref, loc);
816             }
817         }
818       else if (transferType == TT_GLOBPASS)
819         {
820           if (report &&
821               optgenerror 
822               (FLG_COMPDEF,
823                message 
824                ("Function called with global %q not completely defined%q",
825                 sRef_unparse (sRef_getRootBase (fref)),
826                 defExpl (fref)),
827                loc))
828             {
829               sRef_showStateInfo (fref);
830               sRef_setDefined (fref, loc);
831             }
832         }
833       else if (transferType == TT_PARAMRETURN)
834         {
835           if (report && !topLevel
836               && optgenerror 
837               (FLG_COMPDEF,
838                message ("Function returns storage %q reachable from parameter not "
839                         "completely defined%q",
840                         sRef_unparse (ofref),
841                         defExpl (fref)),
842                loc))
843             {
844               sRef_showStateInfo (fref);
845               sRef_setDefined (fref, loc);
846             }
847         }
848       else if (transferType == TT_LEAVETRANS)
849         {
850           if (report && !topLevel
851               && optgenerror 
852               (FLG_COMPDEF,
853                message ("Scope exits with storage %q reachable from "
854                         "temporary reference not completely defined%q",
855                         sRef_unparse (ofref),
856                         defExpl (fref)),
857                loc))
858             {
859               sRef_showStateInfo (fref);
860               sRef_setDefined (fref, loc);
861             }
862         }
863       else 
864         {
865           if (transferType != TT_DOASSIGN
866               && (!(sRef_isNew (fref) || sRef_isType (fref))))
867             {
868               if (report)
869                 {
870                   DPRINTF (("Here we are: %s", sRef_unparseFull (fref)));
871
872                   if (sRef_isDead (fref))
873                     {
874                       if (optgenerror 
875                           (FLG_USERELEASED,
876                            message ("%s storage %qwas released: %q",
877                                     transferType_unparse (transferType),
878                                     sRef_unparseOpt (fref), 
879                                     generateText (fexp, texp, tref, transferType)),
880                            loc))
881                         {
882                           sRef_showStateInfo (fref);
883                         }
884                     }
885                   else 
886                     {
887                       if (optgenerror 
888                           (FLG_COMPDEF,
889                            message 
890                            ("%s storage %qnot completely defined%q: %q",
891                             transferType_unparse (transferType),
892                             sRef_unparseOpt (ofref),
893                             defExpl (fref),
894                             generateText (fexp, texp, tref, transferType)),
895                            loc))
896                         {
897                           sRef rb = sRef_getRootBase (fref);
898                           sRef_showStateInfo (fref);
899                           
900                           sRef_setDefinedCompleteDirect (rb, loc);
901                         }
902                     }
903                 }
904             }
905           else
906             {
907
908               if (sRef_isAllocated (fref) && sRef_isValid (tref) 
909                   && (transferType == TT_DOASSIGN))
910                 {
911                   sRef_setAllocatedComplete (tref, loc);
912                 }
913               return YES;
914             }
915         }
916
917       return NO;
918     }
919   
920   if (ctype_isUnknown (ct))
921     {
922       return YES;
923     }
924   else if (ctype_isPointer (ct) || ctype_isArray (ct)) /* evans 2001-07-12 added ctype_isArray */
925     {
926       ctype tct = ctype_realType (sRef_getType (tref));
927
928       if (sRef_isStateUnknown (fref))
929         {
930           return NO;
931         }
932       else
933         {
934           DPRINTF (("Here fref: %s", sRef_unparseFull (fref)));
935           DPRINTF (("Here tref: %s", sRef_unparseFull (tref)));
936
937           if (ctype_isAP (tct) || ctype_isUnknown (tct))
938             {
939               sRef fptr = sRef_constructDeref (fref);
940               sRef tptr = sRef_constructDeref (tref);
941
942               DPRINTF (("Here tptr: %s", sRef_unparseFull (tptr)));
943
944               return (checkCompletelyDefined (fexp, fptr, ofref,
945                                               texp, tptr,
946                                               FALSE, inUnion, FALSE, loc, 
947                                               transferType, depth + 1, report));
948             }
949           else
950             {
951               return YES;
952             }
953         }
954     }
955   else if (ctype_isStruct (ct))
956     {
957       ctype tct = ctype_realType (sRef_getType (tref));
958
959       DPRINTF (("Struct defined: %s", ctype_unparse (tct)));
960
961       if (ctype_match (ct, tct))
962         {
963           bool isOk = TRUE;
964           bool hasOneDefined = FALSE;
965           cstringSList badFields = cstringSList_undefined;
966           
967           if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref)) 
968             {
969               return YES;
970             }
971           
972           DPRINTF (("Check field: %s", sRef_unparseFull (fref)));
973
974           if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
975             {
976               DPRINTF (("Is defined: %s", sRef_unparse (fref)));
977
978               sRefSet_realElements (sRef_derivedFields (fref), sr)
979                 {
980                   bool thisField;
981                   
982                   hasOneDefined = TRUE;
983                   
984                   DPRINTF (("Check derived: %s", sRef_unparseFull (sr)));
985
986                   if (sRef_isField (sr))
987                     {
988                       cstring fieldname = sRef_getField (sr);
989                       sRef fldref = sRef_makeField (tref, fieldname);
990                       bool shouldCheck = !sRef_isRecursiveField (fldref);
991                         
992                       if (shouldCheck)
993                         {
994                           thisField = 
995                             ynm_toBoolRelaxed 
996                             (checkCompletelyDefined (fexp, sr, ofref,
997                                                      texp, fldref,
998                                                      FALSE, inUnion, FALSE, loc, 
999                                                      transferType, depth + 1, 
1000                                                      FALSE));
1001                         }
1002                       else
1003                         {
1004                           thisField = TRUE;
1005                         }
1006                       
1007                       if (!thisField)
1008                         {
1009                           isOk = FALSE;
1010                           badFields = cstringSList_add (badFields,
1011                                                         sRef_getField (sr));
1012                         }
1013                     }
1014                 } end_sRefSet_realElements;
1015             }
1016           else if (sRef_isAllocated (fref))
1017             {
1018               /*
1019               ** for structures, each field must be completely defined
1020               */
1021               
1022               uentryList fields = ctype_getFields (ct);
1023               
1024               uentryList_elements (fields, ue)
1025                 {
1026                   bool thisField;
1027                   cstring name = uentry_getRealName (ue);
1028                   sRef ffield = sRef_makeField (fref, name);
1029                   sRef tfield = sRef_makeField (tref, name);
1030                   bool shouldCheck = !sRef_isRecursiveField (tfield);
1031                   
1032                   if (!shouldCheck)
1033                     {
1034                       thisField = TRUE;
1035                     }
1036                   else
1037                     {
1038                       thisField = ynm_toBoolRelaxed
1039                         (checkCompletelyDefined (fexp, ffield, ofref,
1040                                                  texp, tfield,
1041                                                  FALSE, inUnion, FALSE,
1042                                                  loc, transferType,
1043                                                  depth + 1, FALSE));
1044                     }
1045                   
1046                   if (!thisField)
1047                     {
1048                       isOk = FALSE;
1049                       badFields = cstringSList_add (badFields, uentry_rawName (ue));
1050                     }
1051                   else
1052                     {
1053                       hasOneDefined = TRUE;
1054                     }
1055                 } end_uentryList_elements;
1056             }
1057           else
1058             {
1059               DPRINTF (("Not checking: %s", sRef_unparseFull (fref)));
1060             }
1061           
1062           if (!isOk && (!inUnion || hasOneDefined))
1063             {
1064               if (transferType == TT_GLOBRETURN)
1065                 {
1066                   if (optgenerror
1067                       (FLG_COMPDEF,
1068                        message ("Global storage %q contains %d undefined field%& "
1069                                 "when call returns: %q",
1070                                 sRef_unparse (fref),
1071                                 cstringSList_size (badFields),
1072                                 cstringSList_unparseAbbrev (badFields)),
1073                        loc))
1074                     {
1075                       sRef_setDefined (fref, loc);
1076                     }
1077                 }
1078               else if (transferType == TT_GLOBPASS)
1079                 {
1080                   if (optgenerror
1081                       (FLG_COMPDEF,
1082                        message ("Global storage %q contains %d undefined field%& "
1083                                 "before call: %q",
1084                                 sRef_unparse (fref),
1085                                 cstringSList_size (badFields),
1086                                 cstringSList_unparseAbbrev (badFields)),
1087                        loc))
1088                     {
1089                       sRef_setDefined (fref, loc);
1090                     }
1091                 }
1092               else if (transferType == TT_PARAMRETURN)
1093                 {
1094                   if (optgenerror
1095                       (FLG_COMPDEF,
1096                        message ("Storage %qreachable from parameter "
1097                                 "contains %d undefined field%&: %q",
1098                                 sRef_unparseOpt (fref),
1099                                 cstringSList_size (badFields),
1100                                 cstringSList_unparseAbbrev (badFields)),
1101                        loc))
1102                     {
1103                       sRef_setDefined (fref, loc);
1104                     }
1105                 }
1106               else if (transferType == TT_LEAVETRANS)
1107                 {
1108                   /* no error */
1109                 }
1110               else
1111                 {
1112                   if (optgenerror
1113                       (FLG_COMPDEF,
1114                        message ("%s storage %qcontains %d undefined field%&: %q",
1115                                 transferType_unparse (transferType),
1116                                 sRef_unparseOpt (fref),
1117                                 cstringSList_size (badFields),
1118                                 cstringSList_unparseAbbrev (badFields)),
1119                        loc))
1120                     {
1121                       sRef_setDefined (fref, loc);
1122                     }
1123                 }
1124             }
1125           
1126           cstringSList_free (badFields);
1127           
1128           if (inUnion)
1129             {
1130               if (directUnion)
1131                 {
1132                   return (ynm_fromBool (hasOneDefined));
1133                 }
1134               else
1135                 {
1136                   return (MAYBE);
1137                 }
1138             }
1139           else
1140             {
1141               return (ynm_fromBool (!report || isOk));
1142             }
1143         }
1144       else
1145         {
1146           return YES;
1147         }
1148     }
1149   else if (ctype_isUnion (ct))
1150     {
1151       if (sRef_isStateUnknown (fref) || sRef_isAllocated (tref)) 
1152         {
1153           return YES;
1154         }
1155       else 
1156         {
1157           ctype tct = ctype_realType (sRef_getType (tref));
1158           
1159           if (ctype_isKnown (tct) && ctype_match (ct, tct))
1160             {
1161               cstringSList goodFields = cstringSList_new ();
1162               bool isOk = FALSE;
1163               int nelements = sRefSet_size (sRef_derivedFields (fref));       
1164
1165               /*
1166               ** for unions, at least one field must be completely defined
1167               */
1168               
1169               if (sRef_isPdefined (fref) || sRef_isAnyDefined (fref))
1170                 {
1171                   isOk = TRUE;
1172                 }
1173               
1174               sRefSet_realElements (sRef_derivedFields (fref), sr)
1175                 {
1176                   bool thisField;
1177
1178                   if (sRef_isField (sr))
1179                     {
1180                       sRef fldref = sRef_makeField (tref, sRef_getField (sr));
1181
1182                       DPRINTF (("Trying union field: %s", sRef_unparseFull (fldref)));
1183
1184                       thisField = ynm_toBoolStrict 
1185                         (checkCompletelyDefined 
1186                          (fexp, sr, ofref,
1187                           texp, fldref, FALSE, inUnion, 
1188                           (nelements > 1 ? TRUE : FALSE),
1189                           loc, transferType, depth + 1, FALSE));
1190                       
1191                       if (thisField)
1192                         {
1193                           goodFields = cstringSList_add 
1194                             (goodFields, sRef_getField (sr));
1195                         }
1196                     }
1197                 } end_sRefSet_realElements;
1198               
1199               if (cstringSList_empty (goodFields) 
1200                   && !isOk 
1201                   && context_getFlag (FLG_UNIONDEF))
1202                 {
1203                   if (!inUnion)
1204                     {
1205                       if (transferType == TT_PARAMRETURN)
1206                         {
1207                           voptgenerror 
1208                             (FLG_UNIONDEF,
1209                              message ("Union %q reachable from parameter has "
1210                                       "no defined field",
1211                                       sRef_unparse (fref)),
1212                              loc);
1213                         }
1214                       else if (transferType == TT_LEAVETRANS)
1215                         {
1216                           voptgenerror 
1217                             (FLG_UNIONDEF,
1218                              message ("Union %q has no defined field at scope exit",
1219                                       sRef_unparse (fref)),
1220                              loc);
1221                         }
1222                       /* evans 2001-08-21: added this branch for global returns */
1223                       else if (transferType == TT_GLOBRETURN)
1224                         {
1225                           voptgenerror 
1226                             (FLG_UNIONDEF,
1227                              message ("Union %q reachable from global %q has "
1228                                       "no defined field",
1229                                       sRef_unparse (fref),
1230                                       sRef_unparse (sRef_getRootBase (fref))),
1231                              loc);
1232                         }
1233                       else if (transferType == TT_DOASSIGN
1234                                || transferType == TT_FIELDASSIGN
1235                                || transferType == TT_GLOBINIT)
1236                         {
1237                           ; /* no error */
1238                         }
1239                       else
1240                         {
1241                           voptgenerror 
1242                             (FLG_UNIONDEF,
1243                              message ("%s union %q has no defined field",
1244                                       transferType_unparse (transferType),
1245                                       sRef_unparse (fref)),
1246                              loc);
1247                         }
1248                     }
1249                   isOk = FALSE;
1250                 }
1251               
1252               cstringSList_free (goodFields);
1253               return ynm_fromBool (!report || isOk);
1254             }
1255         }
1256     }
1257   else
1258     {
1259       ;
1260     }
1261
1262   return YES;
1263 }
1264
1265 /*
1266 ** fref is being free'd
1267 */
1268
1269 typedef enum {
1270   DSC_GLOB, DSC_LOCAL, DSC_PARAM, DSC_STRUCT
1271   } dscCode;
1272
1273 static /*@observer@*/ cstring dscCode_unparse (dscCode desc) /*@*/
1274 {
1275   switch (desc)
1276     {
1277     case DSC_GLOB:
1278       return cstring_makeLiteralTemp ("killed global");
1279     case DSC_LOCAL:
1280       return cstring_makeLiteralTemp ("variable declared in this scope");
1281     case DSC_PARAM:
1282       return cstring_makeLiteralTemp ("released storage");
1283     case DSC_STRUCT:
1284       return cstring_makeLiteralTemp ("released structure parameter");
1285     }
1286
1287   BADEXIT;
1288 }
1289
1290 static bool 
1291 checkCompletelyDestroyed (exprNode p_fexp, sRef p_fref, bool p_topLevel, bool p_isField,
1292                           fileloc p_loc, int p_depth, dscCode p_desc,
1293                           bool p_hideErrors);
1294
1295 bool transferChecks_globalDestroyed (sRef fref, fileloc loc)
1296 {
1297   DPRINTF (("Global destroyed: %s", sRef_unparseFull (fref)));
1298   return (checkCompletelyDestroyed (exprNode_undefined, fref, TRUE, FALSE,
1299                                     loc, 0, DSC_GLOB, FALSE));
1300 }
1301
1302 void transferChecks_localDestroyed (sRef fref, fileloc loc)
1303 {
1304   if (sRef_isObserver (fref) || sRef_isExposed (fref)
1305       || sRef_isPartial (fref))
1306     {
1307       ;
1308     }
1309   else
1310     {
1311       (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE, FALSE,
1312                                        loc, 0, DSC_LOCAL, FALSE);
1313     }
1314 }
1315
1316 void transferChecks_structDestroyed (sRef fref, fileloc loc)
1317 {
1318   DPRINTF (("Check struct destroyed: %s", sRef_unparse (fref)));
1319
1320   if (sRef_isObserver (fref) || sRef_isExposed (fref)
1321       || sRef_isPartial (fref))
1322     {
1323       DPRINTF (("Its exposed!"));;
1324     }
1325   else
1326     {
1327       (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE, FALSE,
1328                                        loc, 0, DSC_STRUCT, FALSE);
1329     }
1330 }
1331
1332 static bool
1333 checkCompletelyDestroyed (exprNode fexp, sRef fref, bool topLevel, bool isField,
1334                           fileloc loc, int depth,
1335                           dscCode desc, bool hideErrors)
1336 {
1337   ctype ct;
1338   
1339   DPRINTF (("Check completely destroyed: %s / %s",
1340             sRef_unparse (fref),
1341             bool_unparse (hideErrors)));
1342
1343   if (depth > MAXDEPTH)
1344     {
1345       llquietbug (message ("checkCompletelyDestroyed: too deep: %s / %q", 
1346                            exprNode_unparse (fexp),
1347                            sRef_unparseFull (fref)));
1348       return TRUE;
1349     }
1350
1351   if (!sRef_isKnown (fref)) return TRUE;
1352
1353   /* evans 2001-03-24: added this.  Definitely null values are always destroyed. */
1354
1355   if (sRef_isDefinitelyNull (fref))
1356     {
1357       return TRUE;
1358     }
1359
1360   if (sRef_isDependent (fref) || sRef_isShared (fref) || sRef_isKept (fref))
1361     {
1362       return TRUE;
1363     }
1364
1365   {
1366     /*
1367     ** evans 2001-03-24: if there is a dependent reference to this storage,
1368     **    no need to destroy, but make it responsible.
1369     */
1370                                                          
1371     sRef depRef = dependentReference (fref);
1372
1373     DPRINTF (("Destroyed? %s / %s",
1374               sRef_unparseFull (fref),
1375               sRef_unparseFull (depRef)));
1376
1377     DPRINTF (("Aliases: %s", usymtab_unparseAliases ()));
1378
1379     if (sRef_isValid (depRef))
1380       {
1381         /*
1382         ** If the referenced storage was not dependent, we make
1383         ** the reference the owner since it must eventually be
1384         ** destroyed.
1385         */
1386
1387         if (!sRef_isDependent (depRef)) 
1388           {
1389             sRef_setOnly (depRef, loc); /* could be owned? */
1390           }
1391
1392         sRef_kill (fref, loc);
1393         return TRUE;
1394       }
1395   }
1396
1397   ct = ctype_realType (sRef_getType (fref));
1398
1399   if (sRef_isPdefined (fref) 
1400       && ctype_isAP (ct)
1401       && !isField
1402       && !context_getFlag (FLG_STRICTDESTROY))
1403     {
1404       /*
1405       ** Don't report errors for array elements (unless strictdestroy)
1406       ** when at least one appears to have been destroyed.
1407       */
1408
1409       DPRINTF (("Partial: %s / hiding errors: %s", sRef_unparseFull (fref),
1410                 ctype_unparse (ct)));
1411       hideErrors = TRUE;
1412       /* Don't report any more errors, but still change ownership. */
1413     }
1414   
1415   if (usymtab_isDefinitelyNull (fref)) 
1416     {
1417       DPRINTF (("Probably null!"));
1418       return TRUE;
1419     }
1420
1421   /*
1422   ** evans 2002-01-02: removed this
1423   ** if (!context_flagOn (FLG_COMPDESTROY, loc)) 
1424   ** {
1425   ** return TRUE;
1426   ** }
1427   ** 
1428   ** if (!context_getFlag (FLG_MUSTFREEONLY)) return TRUE;
1429   */
1430   
1431   DPRINTF (("Here: %s", ctype_unparse (ct)));
1432
1433   if (!topLevel)
1434     {
1435       bool docheck = FALSE;
1436       bool reportederror;
1437
1438       if (sRef_isFresh (fref) || sRef_isOnly (fref))
1439         {
1440           docheck = TRUE;
1441           
1442           DPRINTF (("Here: %s", ctype_unparse (ct)));
1443           if (sRef_isDead (fref) 
1444               || sRef_isUnuseable (fref)
1445               || sRef_definitelyNull (fref)
1446               || sRef_isObserver (fref) 
1447               || sRef_isExposed (fref))
1448             {
1449               docheck = FALSE;
1450             }
1451         }
1452       
1453       if (docheck)
1454         {
1455           if (sRef_isPossiblyDead (fref) || sRef_isRelDef (fref))
1456             {
1457               if (exprNode_isDefined (fexp))
1458                 {
1459                   reportederror = 
1460                     !hideErrors 
1461                     && 
1462                     optgenerror2 
1463                     (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1464                      message ("Only storage %q (type %s) derived from %s "
1465                               "may not have been released: %s",
1466                               sRef_unparse (fref), 
1467                               ctype_unparse (sRef_getType (fref)),
1468                               dscCode_unparse (desc),
1469                               exprNode_unparse (fexp)),
1470                      loc);
1471                 }
1472               else
1473                 {
1474                   reportederror =
1475                     !hideErrors
1476                     &&
1477                     optgenerror2 
1478                     (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1479                      message 
1480                      ("Only storage %q (type %s) derived from %s "
1481                       "may not have been released",
1482                       sRef_unparse (fref), 
1483                       ctype_unparse (sRef_getType (fref)),
1484                       dscCode_unparse (desc)),
1485                      loc);
1486                 }
1487               
1488               if (reportederror)
1489                 {
1490                   sRef_kill (fref, loc); /* prevent further errors */
1491                 }
1492             }
1493           else 
1494             {
1495               if (sRef_isStateUndefined (fref))
1496                 {
1497                   DPRINTF (("Here: %s", ctype_unparse (ct)));
1498                   return TRUE;
1499                 }
1500               else
1501                 {
1502                   if (exprNode_isDefined (fexp))
1503                     {
1504                       DPRINTF (("Here: %s", sRef_unparseFull (fref)));
1505
1506                       reportederror =
1507                         !hideErrors
1508                         &&
1509                         optgenerror 
1510                         (FLG_COMPDESTROY,
1511                          message ("Only storage %q (type %s) derived from %s "
1512                                   "is not released (memory leak): %s",
1513                                   sRef_unparse (fref),
1514                                   ctype_unparse (sRef_getType (fref)),  
1515                                   dscCode_unparse (desc),
1516                                   exprNode_unparse (fexp)),
1517                          loc);
1518                     }
1519                   else
1520                     {
1521                       reportederror = 
1522                         !hideErrors
1523                         &&
1524                         optgenerror 
1525                         (FLG_COMPDESTROY,
1526                          message ("Only storage %q (type %s) derived from %s "
1527                                   "is not released (memory leak)",
1528                                   sRef_unparse (fref),
1529                                   ctype_unparse (sRef_getType (fref)),
1530                                   dscCode_unparse (desc)),
1531                          loc);
1532                     }
1533
1534                   if (reportederror)
1535                     {
1536                       hideErrors = TRUE;
1537                       
1538                       /* sRef_kill (fref, loc); */ /* prevent further errors */
1539                       DPRINTF (("Killed: %s", sRef_unparseFull (fref)));
1540                     }
1541                 }
1542             }
1543
1544           DPRINTF (("Here: %s", ctype_unparse (ct)));
1545           return FALSE;
1546         }
1547       
1548       if (/*! evs-2002-03-24 sRef_isAnyDefined (fref) || */
1549           sRef_isDead (fref)
1550           || (sRef_isPdefined (fref) 
1551               && sRefSet_isEmpty (sRef_derivedFields (fref)))) 
1552         {
1553           DPRINTF (("Here: %s [%s / %s]", 
1554                     sRef_unparseFull (fref),
1555                     bool_unparse (sRef_isAnyDefined (fref)),
1556                     bool_unparse (sRef_isDead (fref))));
1557           return TRUE; 
1558         }
1559     }
1560
1561   DPRINTF (("Here..."));
1562
1563   if (ctype_isPointer (ct))
1564     {
1565       sRef fptr = sRef_constructDeadDeref (fref);
1566       bool res;
1567
1568       res = checkCompletelyDestroyed (fexp, fptr, FALSE, FALSE,
1569                                       loc, depth + 1, desc, hideErrors);
1570       
1571       return res;
1572     }
1573   else if (ctype_isArray (ct))
1574     {
1575       if ((sRef_isStateUnknown (fref) || sRef_isAllocated (fref))
1576           && !sRef_hasDerived (fref))
1577         {
1578           /*
1579           ** Bogosity necessary to prevent infinite depth.
1580           */
1581
1582           return FALSE;
1583         }
1584       else
1585         {
1586           sRef farr = sRef_constructDeadDeref (fref);
1587           
1588           return (checkCompletelyDestroyed (fexp, farr, FALSE, FALSE,
1589                                             loc, depth + 1, desc, hideErrors));
1590         }
1591     }
1592   else if (ctype_isStruct (ct))
1593     {
1594       /*
1595       ** for structures, each field must be completely destroyed
1596       */
1597
1598       bool isOk = TRUE;
1599       uentryList fields = ctype_getFields (ct);
1600
1601       DPRINTF (("Struct fields: %s", uentryList_unparse (fields)));
1602
1603       if (depth >= MAXDEPTH)
1604         {
1605           llquietbug (message ("checkCompletelyDestroyed (fields): too deep: %s / %q", 
1606                                exprNode_unparse (fexp),
1607                                sRef_unparseFull (fref)));
1608                               
1609           return TRUE;
1610         }
1611       else
1612         {
1613           uentryList_elements (fields, ue)
1614             {
1615               sRef field = sRef_makeField (fref, uentry_rawName (ue));
1616               
1617               /*
1618               ** note order of && operands --- want to report multiple errors
1619               */
1620               
1621               DPRINTF (("Check field: %s", sRef_unparseFull (field)));
1622
1623               isOk = (checkCompletelyDestroyed (fexp, field, FALSE, TRUE,
1624                                                 loc, depth + 1, desc, hideErrors)
1625                       && isOk);
1626             } end_uentryList_elements;
1627         }
1628       
1629       return isOk;
1630     }
1631   else
1632     {
1633       return TRUE;
1634     }
1635 }
1636
1637 void
1638 transferChecks_return (exprNode fexp, uentry rval)
1639 {
1640   sRef uref = uentry_getSref (rval);
1641   sRef rref = sRef_makeNew (sRef_getType (uref), uref, cstring_undefined);
1642   uentry fcn = context_getHeader ();
1643   sRef fref = exprNode_getSref (fexp);
1644   stateClauseList clauses = uentry_getStateClauseList (fcn);
1645   
1646   DPRINTF (("Check return: %s as %s = %s",
1647             exprNode_unparse (fexp),
1648             sRef_unparseFull (uref),
1649             sRef_unparseFull (rref)));
1650
1651   /* evans 2001-07-18: removed: if (sRef_isStateSpecial (rref)) */
1652
1653   DPRINTF (("Check state clauses: %s",
1654             stateClauseList_unparse (clauses)));
1655   
1656   stateClauseList_postElements (clauses, cl)
1657     {
1658       if (stateClause_isGlobal (cl))
1659         {
1660           ; 
1661         }
1662       else if (stateClause_setsMetaState (cl))
1663         {
1664           sRefSet refs = stateClause_getRefs (cl);
1665           qual ql = stateClause_getMetaQual (cl);
1666           annotationInfo ainfo = qual_getAnnotationInfo (ql);
1667           metaStateInfo minfo = annotationInfo_getState (ainfo);
1668           cstring key = metaStateInfo_getName (minfo);
1669           int mvalue = annotationInfo_getValue (ainfo);
1670           
1671           DPRINTF (("Return check: %s", stateClause_unparse (cl)));
1672           
1673           sRefSet_elements (refs, el)
1674             {
1675               sRef base = sRef_getRootBase (el);
1676               
1677               DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
1678               
1679               if (sRef_isResult (base))
1680                 {
1681                   sRef sr = sRef_fixBase (el, fref);
1682                   
1683                   if (!sRef_checkMetaStateValue (sr, key, mvalue))
1684                     {
1685                       if (optgenerror 
1686                           (FLG_STATETRANSFER,
1687                            message ("Result state %q does not satisfy ensures "
1688                                     "clause: %q (state is %q, should be %s): %s",
1689                                     sRef_unparse (sr),
1690                                     stateClause_unparse (cl),
1691                                     stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
1692                                                              minfo),
1693                                     metaStateInfo_unparseValue (minfo, mvalue),
1694                                     exprNode_unparse (fexp)),
1695                            exprNode_loc (fexp)))
1696                         {
1697                           sRef_showAliasInfo (sr); 
1698                         }
1699                     }
1700                 }
1701               else 
1702                 {
1703                   /*
1704                   ** Non-results are checked in exit scope.
1705                   */
1706                 }
1707             } end_sRefSet_elements ;
1708         }
1709       else
1710         {
1711           sRefSet refs = stateClause_getRefs (cl);
1712           sRefTest tst = stateClause_getPostTestFunction (cl);
1713           sRefMod modf = stateClause_getReturnEffectFunction (cl);
1714           
1715           DPRINTF (("Clause: %s / %s",
1716                     stateClause_unparse (cl),
1717                     sRefSet_unparse (refs)));
1718           
1719           sRefSet_elements (refs, el)
1720             {
1721               sRef base = sRef_getRootBase (el);
1722               
1723               DPRINTF (("el: %s / %s", sRef_unparse (el),
1724                         sRef_unparse (base)));
1725               
1726               if (sRef_isResult (base) 
1727                   && !sRef_isDefinitelyNull (fref)) /* evans 2002-07-22: don't report allocation errors for null results */
1728                 {
1729                   sRef sr = sRef_fixBase (el, fref);
1730                   
1731                   if (tst != NULL && !(tst (sr)))
1732                     {
1733                       if (optgenerror 
1734                           (stateClause_postErrorCode (cl),
1735                            message ("%s storage %q corresponds to "
1736                                     "storage %q listed in %q clause: %s",
1737                                     stateClause_postErrorString (cl, sr),
1738                                     sRef_unparse (sr),
1739                                     sRef_unparse (el),
1740                                     stateClause_unparseKind (cl),
1741                                     exprNode_unparse (fexp)),
1742                            exprNode_loc (fexp)))
1743                         {
1744                           sRefShower ss = stateClause_getPostTestShower (cl);
1745                           
1746                           if (ss != NULL)
1747                             {
1748                               ss (sr);
1749                             }
1750                         }
1751                     }
1752                   
1753                   if (modf != NULL)
1754                     {
1755                       modf (sr, exprNode_loc (fexp));
1756                     }
1757                 }
1758               else
1759                 {
1760                   /* 
1761                   ** Non-results are checked in exit scope.
1762                   */
1763                 }
1764             } end_sRefSet_elements ;
1765         }
1766     } end_stateClauseList_postElements ;
1767   
1768   if (ctype_isRealSU (exprNode_getType (fexp)))
1769     {
1770       sRef ffref = exprNode_getSref (fexp);
1771           
1772       checkStructTransfer (exprNode_undefined, rref, 
1773                            fexp, ffref,
1774                            exprNode_loc (fexp),
1775                            TT_FCNRETURN);
1776     }
1777   else
1778     {
1779       (void) checkTransfer (fexp, exprNode_getSref (fexp),
1780                             exprNode_undefined, rref, 
1781                             exprNode_undefined,
1782                             exprNode_loc (fexp), TT_FCNRETURN);
1783     }
1784 }
1785
1786 static void
1787   checkPassstateClauseList (uentry ue, exprNode fexp, sRef fref, int argno)
1788 {
1789   stateClauseList clauses = uentry_getStateClauseList (ue);
1790
1791   DPRINTF (("Check pass special: %s / %s",
1792             exprNode_unparse (fexp), sRef_unparseFull (fref)));
1793   
1794   stateClauseList_preElements (clauses, cl)
1795     {
1796       if (stateClause_isGlobal (cl))
1797         {
1798           ;
1799         }
1800       else
1801         {
1802           sRefSet refs = stateClause_getRefs (cl);
1803           sRefTest tst = stateClause_getPreTestFunction (cl);
1804           sRefMod modf = stateClause_getEffectFunction (cl);
1805           
1806           sRefSet_elements (refs, el)
1807             {
1808               sRef base = sRef_getRootBase (el);
1809               
1810               if (sRef_isResult (base))
1811                 {
1812                   ; /* nothing to check before */
1813                 }
1814               else if (sRef_isParam (base))
1815                 {
1816                   if (sRef_getParam (base) == argno - 1)
1817                     {
1818                       sRef sb;
1819                       
1820                       DPRINTF (("Fix base: %s / %s",
1821                                 sRef_unparseFull (el),
1822                                 sRef_unparseFull (fref)));
1823                       
1824                       sb = sRef_fixBase (el, fref);
1825                       
1826                       if (tst != NULL && !(tst(sb)))
1827                         {
1828                           voptgenerror 
1829                             (stateClause_preErrorCode (cl),
1830                              message ("%s storage %qcorresponds to "
1831                                       "storage listed in %q clause of "
1832                                       "called function: %s",
1833                                       stateClause_preErrorString (cl, sb),
1834                                       sRef_unparseOpt (sb),
1835                                       stateClause_unparseKind (cl),
1836                                       exprNode_unparse (fexp)),
1837                              exprNode_loc (fexp));
1838                         }
1839                       
1840                       if (modf != NULL)
1841                         {
1842                           DPRINTF (("Fixing: %s", sRef_unparseFull (sb)));
1843                           modf (sb, exprNode_loc (fexp));
1844                           DPRINTF (("==> %s", sRef_unparseFull (sb)));
1845                         }
1846                     }
1847                 }
1848               else
1849                 {
1850                   BADBRANCH;
1851                 }
1852             } end_sRefSet_elements ;      
1853         }
1854     } end_stateClauseList_preElements ;
1855
1856     DPRINTF (("After: %s", sRef_unparseFull (fref)));
1857 }
1858
1859 /*
1860 ** should not modify arg
1861 */
1862
1863 void
1864 transferChecks_passParam (exprNode fexp, uentry arg, bool isSpec,
1865                           /*@dependent@*/ exprNode fcn, int argno, int totargs)
1866 {
1867   sRef tref = uentry_getSref (arg);
1868   sRef fref = exprNode_getSref (fexp);
1869   bool isOut = FALSE;
1870   bool isPartial = FALSE;
1871   bool isImpOut = FALSE;
1872   ctype ct = uentry_getType (arg);
1873
1874   DPRINTF (("Check pass: %s -> %s",
1875             sRef_unparseFull (fref),
1876             sRef_unparseFull (tref)));
1877   
1878   atFunction = fcn;
1879   atArgNo = argno;
1880   atNumArgs = totargs;
1881
1882   if (ctype_isElips (ct))
1883     {
1884       ct = ctype_unknown;
1885     }
1886
1887   DPRINTF (("Out arg: %s", bool_unparse (uentry_isOut (arg))));
1888
1889   if (!ctype_isElips (ct) && 
1890       (ctype_isVoidPointer (ct) && uentry_isOut (arg) && sRef_isOnly (tref)))
1891     {
1892       if (ctype_isRealAP (ct))
1893         {
1894           if (sRef_aliasCheckSimplePred (sRef_isDead, fref))
1895             {
1896               if (optgenerror
1897                   (FLG_USERELEASED,
1898                    message ("Dead storage %qpassed as out parameter to %s: %s",
1899                             sRef_unparseOpt (fref),
1900                             exprNode_unparse (fcn),
1901                             exprNode_unparse (fexp)),
1902                    exprNode_loc (fexp)))
1903                 {
1904                   if (sRef_isDead (fref))
1905                     {
1906                       sRef_showStateInfo (fref);
1907                     }
1908                   else
1909                     {
1910                       DPRINTF (("Not really dead!"));
1911                       sRef_showStateInfo (fref);
1912                     }
1913                 }
1914               
1915               sRef_setAllocated (fref, exprNode_loc (fexp));
1916             }
1917           else if (context_getFlag (FLG_STRICTUSERELEASED)
1918                    && sRef_aliasCheckSimplePred (sRef_isPossiblyDead, fref))
1919             {
1920               if (optgenerror2 
1921                   (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1922                    message ("Possibly dead storage %qpassed as out parameter: %s",
1923                             sRef_unparseOpt (fref),
1924                             exprNode_unparse (fexp)),
1925                    exprNode_loc (fexp)))
1926                 {
1927                   if (sRef_isPossiblyDead (fref))
1928                     {
1929                       sRef_showStateInfo (fref);
1930                     }
1931                 }
1932               
1933               sRef_setAllocated (fref, exprNode_loc (fexp));
1934             }
1935           else if (sRef_aliasCheckSimplePred (sRef_isStateUndefined, fref) 
1936                    || sRef_aliasCheckSimplePred (sRef_isUnuseable, fref))
1937             {
1938               voptgenerror
1939                 (FLG_USEDEF,
1940                  message ("Unallocated storage %qpassed as out parameter: %s",
1941                           sRef_unparseOpt (fref),
1942                           exprNode_unparse (fexp)),
1943                  exprNode_loc (fexp));
1944
1945               sRef_setAllocated (fref, exprNode_loc (fexp));
1946             }
1947           else
1948             {
1949               ;
1950             }
1951         }
1952       
1953       (void) checkCompletelyDestroyed (fexp, fref, TRUE, FALSE,
1954                                        exprNode_loc (fexp), 0, DSC_PARAM, FALSE);
1955
1956       /* make it defined now, so checkTransfer is okay */
1957       sRef_setDefined (fref, exprNode_loc (fexp)); 
1958     }
1959   else if (uentry_isOut (arg))
1960     {
1961       DPRINTF (("Here we are!"));
1962
1963       if (ctype_isRealAP (ct)
1964           && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1965         {
1966           voptgenerror
1967             (FLG_USEDEF,
1968              message ("Unallocated storage %qpassed as out parameter to %s: %s",
1969                       sRef_unparseOpt (fref),
1970                       exprNode_unparse (fcn),
1971                       exprNode_unparse (fexp)),
1972              exprNode_loc (fexp));
1973           sRef_setAllocated (fref, exprNode_loc (fexp));
1974         }
1975       else if (sRef_isDead (fref))
1976         {
1977           if (optgenerror
1978               (FLG_USERELEASED,
1979                message ("Dead storage %qpassed as out parameter to %s: %s",
1980                         sRef_unparseOpt (fref),
1981                         exprNode_unparse (fcn),
1982                         exprNode_unparse (fexp)),
1983                exprNode_loc (fexp)))
1984             {
1985               sRef_showStateInfo (fref);
1986               sRef_setAllocated (fref, exprNode_loc (fexp));
1987             }
1988         }
1989       else if (sRef_isPossiblyDead (fref))
1990         {
1991           if (optgenerror2
1992               (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1993                message ("Possibly dead storage %qpassed as out parameter to %s: %s",
1994                         sRef_unparseOpt (fref),
1995                         exprNode_unparse (fcn),
1996                         exprNode_unparse (fexp)),
1997                exprNode_loc (fexp)))
1998             {
1999               sRef_showStateInfo (fref);
2000               sRef_setAllocated (fref, exprNode_loc (fexp));
2001             }
2002         }
2003       else
2004         {
2005           ;
2006         }
2007       
2008       isOut = TRUE;
2009     }
2010   else if (uentry_isPartial (arg))
2011     {
2012       if (ctype_isRealAP (ct) 
2013           && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
2014         {
2015           voptgenerror 
2016             (FLG_USEDEF,
2017              message ("Unallocated storage %qpassed as partial parameter: %s",
2018                       sRef_unparseOpt (fref),
2019                       exprNode_unparse (fexp)),
2020              exprNode_loc (fexp));
2021           sRef_setAllocated (fref, exprNode_loc (fexp));
2022         }
2023       else if (sRef_isDead (fref))
2024         {
2025           if (optgenerror
2026               (FLG_USERELEASED,
2027                message ("Dead storage %qpassed as partial parameter to %s: %s",
2028                         sRef_unparseOpt (fref),
2029                         exprNode_unparse (fcn),
2030                         exprNode_unparse (fexp)),
2031                exprNode_loc (fexp)))
2032             {
2033               sRef_showStateInfo (fref);
2034               sRef_setAllocated (fref, exprNode_loc (fexp));
2035             }
2036         }
2037       else if (sRef_isPossiblyDead (fref))
2038         {
2039           if (optgenerror2
2040               (FLG_USERELEASED, FLG_STRICTUSERELEASED,
2041                message ("Possibly dead storage %qpassed as partial parameter to %s: %s",
2042                         sRef_unparseOpt (fref),
2043                         exprNode_unparse (fcn),
2044                         exprNode_unparse (fexp)),
2045                exprNode_loc (fexp)))
2046             {
2047               sRef_showStateInfo (fref);
2048               sRef_setAllocated (fref, exprNode_loc (fexp));
2049             }
2050         }
2051       else
2052         {
2053           ;
2054         }
2055
2056       isPartial = TRUE;
2057     }
2058   else if (uentry_isStateSpecial (arg))
2059     {
2060       uentry ue = exprNode_getUentry (fcn);
2061
2062       if (ctype_isRealAP (ct) 
2063           && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
2064         {
2065           voptgenerror 
2066             (FLG_USEDEF,
2067              message ("Unallocated storage %qpassed as special parameter: %s",
2068                       sRef_unparseOpt (fref),
2069                       exprNode_unparse (fexp)),
2070              exprNode_loc (fexp));
2071           sRef_setAllocated (fref, exprNode_loc (fexp));
2072         }
2073       else if (sRef_isDead (fref))
2074         {
2075           if (optgenerror
2076               (FLG_USERELEASED,
2077                message ("Dead storage %qpassed as special parameter to %s: %s",
2078                         sRef_unparseOpt (fref),
2079                         exprNode_unparse (fcn),
2080                         exprNode_unparse (fexp)),
2081                exprNode_loc (fexp)))
2082             {
2083               sRef_showStateInfo (fref);
2084               sRef_setAllocated (fref, exprNode_loc (fexp));
2085             }
2086         }
2087       else if (sRef_isPossiblyDead (fref))
2088         {
2089           if (optgenerror2
2090               (FLG_USERELEASED, FLG_STRICTUSERELEASED,
2091                message ("Possibly dead storage %qpassed as special parameter to %s: %s",
2092                         sRef_unparseOpt (fref),
2093                         exprNode_unparse (fcn),
2094                         exprNode_unparse (fexp)),
2095                exprNode_loc (fexp)))
2096             {
2097               sRef_showStateInfo (fref);
2098               sRef_setAllocated (fref, exprNode_loc (fexp));
2099             }
2100         }
2101       else
2102         {
2103           ;
2104         }
2105
2106       if (uentry_hasStateClauseList (ue))
2107         {
2108           checkPassstateClauseList (ue, fexp, fref, argno);
2109         }
2110       
2111       return; /* ??? */
2112     }
2113   else if (sRef_isStateDefined (tref))
2114     {
2115       exprNode_checkUseParam (fexp);
2116     }
2117   else
2118     {
2119       if (isSpec || (!context_getFlag (FLG_IMPOUTS)))
2120         {
2121           exprNode_checkUseParam (fexp);
2122         }
2123       else
2124         {
2125           if (!sRef_isMacroParamRef (fref) 
2126               && (ctype_isRealAP (ct)))
2127             {
2128               if (sRef_isAddress (fref))
2129                 {
2130                   if (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref))
2131                     {
2132                       voptgenerror 
2133                         (FLG_USEDEF,
2134                          message 
2135                          ("Unallocated address %qpassed as implicit "
2136                           "out parameter: %s",
2137                           sRef_unparseOpt (fref),
2138                           exprNode_unparse (fexp)),
2139                          exprNode_loc (fexp));
2140                       sRef_setAllocated (fref, exprNode_loc (fexp));
2141                     }
2142                 }
2143               
2144               /* yes, I really mean this! */
2145               tref = sRef_copy (tref);
2146               sRef_setAllocated (tref, exprNode_loc (fexp)); 
2147
2148               isOut = TRUE;
2149               isImpOut = TRUE;
2150             }
2151           else 
2152             {
2153               exprNode_checkUseParam (fexp);
2154             }
2155         }
2156     }
2157
2158   if (sRef_isNew (fref))
2159     {
2160       alkind tkind = sRef_getAliasKind (tref);
2161
2162       if ((sRef_isFresh (fref) || sRef_isOnly (fref))
2163           && !alkind_isOnly (tkind) 
2164           && !alkind_isKeep (tkind) 
2165           && !alkind_isOwned (tkind)
2166           && !alkind_isError (tkind)
2167           && !uentry_isReturned (arg))
2168         
2169         {
2170           voptgenerror 
2171             (FLG_MUSTFREEFRESH,
2172              message ("New fresh storage %q(type %s) passed as %s (not released): %s",
2173                       sRef_unparseOpt (fref),
2174                       ctype_unparse (sRef_getType (fref)),
2175                       alkind_unparse (sRef_getAliasKind (tref)),
2176                       exprNode_unparse (fexp)),
2177              exprNode_loc (fexp));
2178
2179           DPRINTF (("Fresh: %s", sRef_unparseFull (fref)));
2180         }
2181       else 
2182         {
2183           if (sRef_isNewRef (fref) && !sRef_isKillRef (tref))
2184             {
2185               alkind ak = sRef_getAliasKind (tref);
2186               
2187               if (!alkind_isError (ak))
2188                 {
2189                   voptgenerror 
2190                     (FLG_MUSTFREEFRESH,
2191                      message ("New reference %q(type %s) passed as %s (not released): %s",
2192                               sRef_unparseOpt (fref),
2193                               ctype_unparse (sRef_getType (fref)),
2194                               alkind_unparse (sRef_getAliasKind (tref)),
2195                               exprNode_unparse (fexp)),
2196                      exprNode_loc (fexp));
2197                 }
2198             }
2199         }
2200     }
2201   
2202   (void) checkTransfer (fexp, exprNode_getSref (fexp),
2203                         exprNode_undefined, tref,
2204                         fcn,
2205                         exprNode_loc (fexp), TT_FCNPASS);
2206
2207   setCodePoint ();
2208   fref = exprNode_getSref (fexp);
2209   
2210   if (isOut && !sRef_isDead (fref) && !sRef_isPossiblyDead (fref))
2211     {
2212       sRef base;
2213
2214       if (ctype_isRealAP (sRef_getType (fref)))
2215         {
2216           base = sRef_makePointer (fref); 
2217         }
2218       else
2219         {
2220           base = fref;
2221         }
2222
2223       if (isImpOut)
2224         {
2225           exprNode_checkMSet (fexp, base);
2226         }
2227       else
2228         {
2229           exprNode_checkSet (fexp, base);
2230         }
2231
2232       if (sRef_isValid (base))
2233         {
2234           setCodePoint ();
2235
2236           sRef_clearDerived (base);
2237           sRef_setDefined (base, exprNode_loc (fexp));
2238           usymtab_clearAlias (base);
2239           sRef_setNullUnknown (base, exprNode_loc (fexp));
2240         }
2241     }
2242
2243   if (isPartial)
2244     {
2245       if (sRef_isValid (fref))
2246         {
2247           sRef_setPartial (fref, exprNode_loc (fexp)); 
2248         }
2249     }
2250
2251   atFunction = exprNode_undefined;
2252   atArgNo = 0;
2253   atNumArgs = 0;
2254   
2255   /* need to fixup here: derived refs could be bogus */
2256   /* (better to change sRef to not add derivs for "protected" ref) */
2257
2258   uentry_fixupSref (arg);
2259
2260   setCodePoint ();
2261
2262   DPRINTF (("Check pass: ==> %s",
2263             sRef_unparseFull (fref)));
2264 }
2265
2266 void
2267 transferChecks_globalReturn (uentry glob)
2268 {
2269   sRef_protectDerivs ();
2270   checkGlobTrans (glob, TT_GLOBRETURN);
2271   sRef_clearProtectDerivs ();
2272 }
2273
2274 void transferChecks_paramReturn (uentry actual)
2275 {
2276   checkLeaveTrans (actual, TT_PARAMRETURN);
2277 }
2278
2279 void transferChecks_loseReference (uentry actual)
2280 {
2281   checkLeaveTrans (actual, TT_LEAVETRANS);
2282 }
2283
2284 static void
2285 checkLeaveTrans (uentry actual, transferKind transferType)
2286 {
2287   sRef aref = uentry_getSref (actual);
2288   sRef origref = uentry_getOrigSref (actual);
2289
2290   if (transferType == TT_PARAMRETURN 
2291       && (sRef_isKeep (origref) || sRef_isOnly (origref)
2292           || sRef_isOwned (origref)))
2293     {
2294       /* caller cannot use, nothing to check */
2295     }
2296   else
2297     {
2298       if (sRef_isNSLocalVar (origref))
2299         {
2300           ;
2301         }
2302       else
2303         {
2304           DPRINTF (("Leave trans: %s", uentry_unparseFull (actual)));
2305
2306           (void) checkCompletelyDefined (exprNode_undefined, aref, aref,
2307                                          exprNode_undefined, origref,
2308                                          TRUE, FALSE, FALSE,
2309                                          g_currentloc, transferType,
2310                                          0, TRUE);
2311         }
2312     }
2313 }
2314
2315 static void
2316 checkGlobTrans (uentry glob, transferKind type)
2317 {
2318   sRef eref = uentry_getOrigSref (glob);
2319  
2320   DPRINTF (("Completely defined: %s", uentry_unparseFull (glob)));
2321
2322   (void) checkCompletelyDefined (exprNode_undefined, uentry_getSref (glob), 
2323                                  uentry_getSref (glob),
2324                                  exprNode_undefined, eref, 
2325                                  TRUE, FALSE, FALSE,
2326                                  g_currentloc, type, 0, TRUE);
2327 }
2328
2329 /*
2330 ** For lhs of assignment, alias kind is set from basic type.
2331 ** Yoikes!
2332 */
2333
2334 static void
2335 fixAssignLhs (sRef s)
2336 {
2337   sRef_resetStateComplete (s);
2338 }
2339
2340 static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srhs,
2341                                  fileloc loc,
2342                                  transferKind tt)
2343 {
2344   ctype st = ctype_realType (sRef_getType (srhs));
2345   
2346   if (ctype_isSU (st) && ctype_isRealSU (sRef_getType (slhs))
2347       && ctype_match (sRef_getType (slhs), st))
2348     {
2349       if (tt == TT_DOASSIGN && sRef_isStateDefined (srhs))
2350         {
2351           sRef_setDefinedComplete (slhs, loc);
2352         }
2353           
2354       if (sRef_isDependent (slhs)
2355           || sRef_isObserver (slhs)
2356           || sRef_isExposed (slhs))
2357         {
2358           ;
2359         }
2360       else
2361         {
2362           if (sRef_isLocalVar (slhs)
2363               && sRef_isFileOrGlobalScope (sRef_getRootBase (srhs)))
2364             {
2365               sRef_setDependent (slhs, exprNode_loc (lhs));
2366             }
2367           else
2368             {
2369               if (ctype_isUnion (st))
2370                 {
2371                   sRef_setDefState (slhs, sRef_getDefState (srhs), 
2372                                     exprNode_loc (lhs));
2373
2374                   sRefSet_realElements (sRef_derivedFields (srhs), sr)
2375                     {
2376                       if (sRef_isField (sr))
2377                         {
2378                           cstring fieldname = sRef_getField (sr);
2379                           sRef lfld = sRef_makeField (slhs, fieldname);
2380
2381                           (void) checkTransfer (rhs, sr, lhs, lfld, 
2382                                                 exprNode_undefined,
2383                                                 exprNode_loc (lhs), tt);
2384                         }
2385                     } end_sRefSet_realElements ;
2386                 }
2387               else
2388                 {
2389                   uentryList fields = ctype_getFields (st);
2390                   
2391                   uentryList_elements (fields, field)
2392                     {
2393                       sRef rfld = sRef_makeField (srhs, uentry_rawName (field));
2394                       sRef lfld = sRef_makeField (slhs, uentry_rawName (field));
2395                       (void) checkTransfer (rhs, rfld, lhs, lfld, 
2396                                             exprNode_undefined,
2397                                             exprNode_loc (lhs), tt);
2398                     } end_uentryList_elements ;
2399                 }
2400
2401               if (sRef_isOnly (srhs))
2402                 {
2403                   sRef_setKeptComplete (srhs, loc);
2404                 }
2405             }
2406         }
2407     }
2408 }
2409
2410 void
2411 transferChecks_initialization (exprNode lhs, exprNode rhs)
2412 {
2413   sRef slhs = exprNode_getSref (lhs);
2414   
2415   if (sRef_isFileOrGlobalScope (slhs) || (!sRef_isCvar (slhs)))
2416     {
2417       (void) checkTransfer (rhs, exprNode_getSref (rhs), 
2418                             lhs, slhs, 
2419                             exprNode_undefined,
2420                             exprNode_loc (rhs), TT_GLOBINIT);
2421     }
2422   else
2423     {
2424       transferChecks_assign (lhs, rhs);
2425     }
2426 }
2427
2428 void
2429 transferChecks_assign (exprNode lhs, exprNode rhs)
2430 {
2431   sRef slhs = exprNode_getSref (lhs);
2432   sRef srhs = exprNode_getSref (rhs);
2433   sRef base = sRef_getBaseSafe (slhs);
2434   nstate ns;
2435   
2436   DPRINTF (("Check assign: %s = %s", exprNode_unparse (lhs),
2437             exprNode_unparse (rhs)));
2438   DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2439   DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2440
2441   if (ctype_isRealSU (sRef_getType (srhs)))
2442     {
2443       checkStructTransfer (lhs, slhs, rhs, srhs, exprNode_loc (lhs), TT_FIELDASSIGN);
2444     }
2445   else
2446     {
2447       DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2448       DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2449       (void) checkTransfer (rhs, srhs, lhs, slhs, 
2450                             exprNode_undefined,
2451                             exprNode_loc (lhs), TT_DOASSIGN);
2452       DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2453       DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2454     }
2455
2456   if (sRef_isConst (srhs) && sRef_isLocalState (srhs))
2457     {
2458       /* constants can match anything (e.g., NULL) */
2459       sRef_setAliasKind (slhs, AK_ERROR, fileloc_undefined);
2460     }
2461
2462   if (sRef_isValid (base) && sRef_isStateDefined (base))
2463     {
2464       sRef_setPdefined (base, g_currentloc); 
2465     }
2466
2467   if (sRef_isPartial (srhs))
2468     {
2469       sRef_setPartial (slhs, exprNode_loc (rhs));
2470     }
2471
2472   ns = sRef_getNullState (srhs);
2473
2474   if (nstate_possiblyNull (ns))
2475     {
2476       if (usymtab_isGuarded (srhs))
2477         {
2478           ns = NS_NOTNULL;
2479         }
2480     }
2481
2482   sRef_setNullStateInnerComplete (slhs, ns, exprNode_loc (rhs));
2483
2484   if (sRef_isExposed (srhs) || sRef_isObserver (srhs))
2485     {
2486       sRef_setExKind (slhs, sRef_getExKind (srhs), exprNode_loc (rhs));
2487     }
2488   
2489   DPRINTF (("Done transfer: %s", sRef_unparseFull (slhs)));
2490 }
2491
2492 static void
2493 checkTransferNullAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2494                       sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2495                       fileloc loc, transferKind transferType)
2496 {
2497   alkind tkind = sRef_getAliasKind (tref);
2498   ctype ttyp = ctype_realType (sRef_getType (tref));
2499
2500   if (ctype_isUnknown (ttyp))
2501     {
2502       ttyp = exprNode_getType (texp);
2503       
2504       if (ctype_isUnknown (ttyp))
2505         {
2506           ttyp = exprNode_getType (fexp);
2507
2508           if (ctype_isUnknown (ttyp))
2509             {
2510               ttyp = sRef_getType (fref);
2511             }
2512         }
2513     }
2514
2515   if (ctype_isFunction (ttyp) && (transferType == TT_FCNRETURN))
2516     {
2517       ttyp = ctype_getReturnType (ttyp);
2518     }
2519
2520   /*
2521   ** check for null (don't need to check aliases??)
2522   */
2523
2524   if (sRef_possiblyNull (fref) 
2525       && !usymtab_isGuarded (fref) 
2526       && ctype_isRealAP (ttyp))
2527     {
2528       if (!alkind_isLocal (tkind) && !alkind_isFresh (tkind)
2529           && !sRef_perhapsNull (tref)
2530           && !(transferType == TT_DOASSIGN))
2531         {
2532           if (transferType == TT_GLOBINIT)
2533             {
2534               if (sRef_isNotNull (tref))
2535                 {
2536                   if (optgenerror
2537                       (FLG_NULLINIT, /* kuldge flag... */
2538                        message ("%s %q initialized to %s value: %q",
2539                                 sRef_getScopeName (tref),
2540                                 sRef_unparse (tref),
2541                                 sRef_nullMessage (fref),
2542                                 generateText (fexp, texp, tref, transferType)),
2543                        loc))
2544                     {
2545                       sRef_showNullInfo (fref);
2546                       sRef_setNullError (tref);
2547                     }
2548                 }
2549               else
2550                 {
2551                   if (optgenerror
2552                       (FLG_NULLASSIGN,
2553                        message ("%s %q initialized to %s value: %q",
2554                                 sRef_getScopeName (tref),
2555                                 sRef_unparse (tref),
2556                                 sRef_nullMessage (fref),
2557                                 generateText (fexp, texp, tref, transferType)),
2558                        loc))
2559                     {
2560                       sRef_showNullInfo (fref);
2561                       sRef_setNullError (tref);
2562                     }
2563                 }
2564             }
2565           else
2566             {
2567               if (optgenerror
2568                   ((transferType == TT_FCNPASS) ? FLG_NULLPASS : FLG_NULLRET,
2569                    message ("%q storage %q%s: %q",
2570                             cstring_capitalize (sRef_nullMessage (fref)),
2571                             sRef_unparseOpt (fref),
2572                             transferNullMessage (transferType), 
2573                             generateText (fexp, texp, tref, transferType)),
2574                    loc))
2575                 {
2576                   sRef_showNullInfo (fref);
2577                   sRef_setNullError (fref);
2578                 }
2579             }
2580         }
2581       else
2582         {
2583           ;
2584         }
2585     }  
2586 }
2587
2588
2589 static void
2590 checkTransferAssignAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2591                         /*@exposed@*/ sRef tref, exprNode texp, bool tfix,
2592                         fileloc loc, transferKind transferType)
2593 {
2594   alkind tkind = sRef_getAliasKind (tref);
2595
2596   /*
2597   ** Assignment to same --- no errors, or state changes.
2598   ** This can happen when returned params are used.
2599   */
2600
2601   if (sRef_sameName (fref, tref))
2602     {
2603       sRef_copyState (tref, fref); 
2604       return;
2605     }
2606   
2607   if ((alkind_isOnly (tkind) || alkind_isFresh (tkind) 
2608        || alkind_isNewRef (tkind) || alkind_isOwned (tkind))
2609       && !(sRef_isDead (tref) 
2610            || sRef_isStateUndefined (tref) 
2611            || sRef_isUnuseable (tref) 
2612            || sRef_isPartial (tref)
2613            || sRef_definitelyNull (tref) 
2614            || sRef_isStackAllocated (tref) 
2615            || sRef_isAllocIndexRef (tref))
2616       && !(sRef_same (fref, tref)) /* okay to assign to self (returned params) */
2617       && !(usymtab_isDefinitelyNull (tref))) 
2618     {
2619       if (transferChecks_canLoseReference (tref, loc))
2620         {
2621           ; /* no error */
2622         }
2623       else
2624         {
2625           flagcode flg = sRef_isFresh (tref) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY;
2626
2627           if (sRef_hasLastReference (tref))
2628             {
2629               if (optgenerror 
2630                   (flg,
2631                    message ("Last reference %q to %s storage %q(type %s) not released "
2632                             "before assignment: %q",
2633                             sRef_unparse (tref),
2634                             alkind_unparse (tkind),
2635                             sRef_unparseOpt (sRef_getAliasInfoRef (tref)),
2636                             ctype_unparse (sRef_getType (tref)),
2637                             generateText (fexp, texp, tref, transferType)),
2638                    loc))
2639                 {
2640                   sRef_showRefLost (tref);
2641                 }
2642             }
2643           else
2644             {
2645               if (context_inGlobalScope ())
2646                 {
2647                   /* no errors for static initializations */
2648                 }
2649               else 
2650                 {
2651                   /*
2652                   ** don't report this error for a[i], since it could
2653                   ** be a new element.
2654                   */
2655                   
2656                   if (alkind_isNewRef (tkind))
2657                     {
2658                       if (optgenerror 
2659                           (flg,
2660                            message 
2661                            ("%q %q(type %s) not released before assignment: %q",
2662                             cstring_makeLiteral
2663                             (alkind_isKillRef (sRef_getOrigAliasKind (tref))
2664                              ? "Kill reference parameter" : "New reference"),
2665                             sRef_unparseOpt (tref),
2666                             ctype_unparse (sRef_getType (tref)),
2667                             generateText (fexp, texp, tref, transferType)),
2668                            loc))
2669                         {
2670                           sRef_showAliasInfo (tref);
2671                           sRef_setAliasKind (tref, AK_ERROR, loc);
2672                         }
2673                     }
2674                   else if
2675                     (!(sRef_isUnknownArrayFetch (tref)
2676                        && !context_getFlag (FLG_STRICTDESTROY))
2677                      && !sRef_isUnionField (tref)
2678                      && !sRef_isRelDef (tref)
2679                      && optgenerror 
2680                      (flg,
2681                       message 
2682                       ("%s storage %q(type %s) not released before assignment: %q",
2683                        alkind_capName (tkind),
2684                        sRef_unparseOpt (tref),
2685                        ctype_unparse (sRef_getType (tref)),
2686                        generateText (fexp, texp, tref, transferType)),
2687                       loc))
2688                     {
2689                       sRef_showAliasInfo (tref);
2690                     }
2691                   else
2692                     {
2693                       ;
2694                     }
2695                 }
2696             }
2697         }
2698     }
2699
2700   fixAssignLhs (tref);
2701
2702   if (sRef_isRefCounted (tref)) /* tkind might not be correct now */
2703     {
2704       if (sRef_isNewRef (fref))
2705         {
2706           sRef_setAliasKind (tref, AK_NEWREF, loc);
2707         }
2708       else if (sRef_isConst (fref))
2709         {
2710           /* for now, constants are not ref counted */
2711           sRef_setAliasKind (tref, AK_ERROR, loc);
2712         }
2713       else
2714         {
2715           ;
2716         }
2717
2718       if (!sRef_isNSLocalVar (tref) 
2719           && sRef_isRefCounted (fref)
2720           && sRef_isStateDefined (fref))
2721         {
2722           voptgenerror 
2723             (FLG_NEWREFTRANS,
2724              message ("New reference %qto reference counted storage: %q",
2725                       sRef_unparseOpt (tref),
2726                       generateText (fexp, texp, tref, transferType)),
2727              loc);
2728         }
2729     }
2730
2731   /*
2732   ** Not for structures and unions, since assignments copy.
2733   */
2734
2735   if (sRef_isStack (fref)
2736       && !ctype_isSU (ctype_realType (sRef_getType (fref))))
2737     {
2738       sRef_setAliasKindComplete (tref, AK_STACK, loc);
2739     }
2740
2741   if (sRef_isNSLocalVar (tref) 
2742       && !sRef_isOwned (tref) /*< should only apply to static >*/
2743       && ctype_isMutable (sRef_getType (tref)))
2744     {
2745       if (sRef_isOnly (fref) && sRef_isNew (fref)) 
2746         {
2747           if (!tfix) 
2748             {
2749               sRef_setFresh (tref, loc);
2750             }
2751         }
2752     }
2753 }
2754
2755 /*
2756 ** requires sRef_isOnly (fref)
2757 */
2758
2759 static void
2760 checkOnlyTransferAux (sRef fref, exprNode fexp, bool ffix,
2761                       sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2762                       fileloc loc, transferKind transferType)
2763 {     
2764   alkind tkind = sRef_getAliasKind (tref);
2765
2766   if (sRef_isExposed (tref) || sRef_isObserver (tref))
2767     {
2768       if (transferType == TT_FCNRETURN && sRef_isNew (fref)
2769           && !alkind_isError (tkind))
2770         {
2771           if (optgenerror 
2772               (FLG_ONLYTRANS,
2773                message ("Only storage %q%q (will not be released): %q",
2774                         sRef_unparseOpt (fref),
2775                         transferErrorMessage (transferType, tkind),
2776                         generateText (fexp, texp, tref, transferType)),
2777                loc))
2778             {
2779               sRef_showAliasInfo (fref);
2780             }
2781         }
2782       
2783       /* no errors for exposed transfers (is this good enough?) */
2784     }
2785   else if (alkind_isOnly (tkind) || alkind_isKeep (tkind) || alkind_isOwned (tkind))
2786     {
2787       ; /* okay */
2788     }
2789   else if ((transferType == TT_FCNPASS)
2790            && (alkind_isUnknown (tkind) 
2791                || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2792     {
2793       if (sRef_isFresh (fref) 
2794           && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2795         {
2796           if (!ffix) sRef_setAliasKind (fref, AK_UNKNOWN, loc); 
2797         }
2798     }
2799   else if (alkind_isLocal (tkind) 
2800            || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2801     {
2802       if ((transferType == TT_DOASSIGN)
2803           && sRef_isNew (fref) 
2804           && sRef_isOnly (fref))
2805         {
2806           bool error = FALSE;
2807
2808           if (alkind_isUnknown (tkind)
2809               && sRef_isFileOrGlobalScope (sRef_getRootBase (tref)))
2810             {
2811               if (optgenerror 
2812                   (FLG_ONLYUNQGLOBALTRANS,
2813                    message ("Only storage %q%q: %q",
2814                             sRef_unparseOpt (fref),
2815                             transferErrorMessage (transferType, tkind),
2816                             generateText (fexp, texp, tref, transferType)),
2817                    loc))
2818                 {
2819                   sRef_showAliasInfo (fref);
2820                   sRef_setAliasKind (tref, AK_ERROR, loc);
2821                   error = TRUE;
2822                 }
2823             }
2824
2825           if (!error && !ffix) 
2826             {
2827               sRef_setFresh (tref, loc);
2828             }
2829         }
2830       else
2831         {
2832           if (alkind_isLocal (tkind))
2833             {
2834               if (sRef_sameName (tref, fref))
2835                 {
2836                   ; /* don't set this --- corresponds to return transfer */
2837                 }
2838               else
2839                 {
2840                   /*
2841                   ** Don't set local to dependent.  Error will
2842                   ** be detected through aliasing.  Except for
2843                   ** arrays.
2844                   */
2845                   
2846                   if (!tfix && sRef_isThroughArrayFetch (fref)
2847                       && context_getFlag (FLG_DEPARRAYS))
2848                     {
2849                       sRef_setDependent (tref, loc);
2850                     }
2851                 }
2852             }
2853           else
2854             {
2855               if (optgenerror 
2856                   (FLG_ONLYTRANS,
2857                    message ("Only storage %q%q: %q",
2858                             sRef_unparseOpt (fref),
2859                             transferErrorMessage (transferType, tkind),
2860                             generateText (fexp, texp, tref, transferType)),
2861                    loc))
2862                 {
2863                   sRef_showAliasInfo (fref);
2864                 }
2865             }
2866         }
2867     }
2868   else
2869     {
2870       if (alkind_isError (tkind) 
2871           || (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT)))
2872         {
2873           flagcode_recordSuppressed (FLG_ONLYTRANS);
2874         }
2875       else
2876         {
2877           if ((alkind_isKept (tkind) || alkind_isStack (tkind) 
2878                || alkind_isDependent (tkind))
2879               && sRef_isNSLocalVar (tref))
2880             {
2881               ; /* okay */
2882             }
2883           else
2884             {
2885               if (optgenerror 
2886                   (FLG_ONLYTRANS,
2887                    message ("Only storage %q%q: %q",
2888                             sRef_unparseOpt (fref),
2889                             transferErrorMessage (transferType, tkind),
2890                             generateText (fexp, texp, tref, transferType)),
2891                    loc))
2892                 {
2893                   sRef_showAliasInfo (fref);
2894                   
2895                   if (transferType == TT_DOASSIGN)
2896                     {
2897                       /*
2898                       ** alias kind unknown to suppress future messages
2899                       */
2900                       
2901                       if (!ffix && sRef_isNSLocalVar (sRef_getRootBase (fref)))
2902                         {
2903                           sRef_clearAliasKind (fref);
2904                         }
2905                     }
2906                 }
2907             }
2908         }
2909     }
2910 }
2911
2912 /*
2913 ** ??? same as checkOnly ?
2914 */
2915
2916 static void
2917 checkOwnedTransferAux (sRef fref, exprNode fexp, bool ffix,
2918                        sRef tref, exprNode texp, bool tfix,
2919                        fileloc loc, transferKind transferType)
2920 {     
2921   alkind tkind = sRef_getAliasKind (tref);
2922
2923   if (sRef_isExposed (tref) || sRef_isObserver (tref))
2924     {
2925       if (transferType == TT_FCNRETURN && sRef_isNew (fref))
2926         {
2927           if (optgenerror 
2928               (FLG_OWNEDTRANS,
2929                message ("Owned storage %q%q (will not be released): %q",
2930                         sRef_unparseOpt (fref),
2931                         transferErrorMessage (transferType, tkind),
2932                         generateText (fexp, texp, tref, transferType)),
2933                loc))
2934             {
2935               sRef_showAliasInfo (fref);
2936             }
2937         }
2938     }
2939   else if (alkind_isOnly (tkind) || alkind_isKeep (tkind) 
2940            || alkind_isDependent (tkind)
2941            || alkind_isOwned (tkind))
2942     {
2943       /* okay */
2944     }
2945   else if (alkind_isLocal (tkind)
2946            || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2947     {
2948       if ((transferType == TT_DOASSIGN)
2949           && sRef_isNew (fref) && sRef_isOnly (fref))
2950         {
2951           if (!tfix) 
2952             { 
2953               sRef_setFresh (tref, loc); 
2954             }
2955         }
2956       else
2957         {
2958         }
2959     }
2960   else if ((transferType == TT_FCNPASS)
2961            && (alkind_isUnknown (tkind) 
2962                || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2963     {
2964       if (sRef_isFresh (fref) 
2965           && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2966         {
2967           if (!ffix) { sRef_clearAliasKind (fref); }
2968         }
2969     }
2970   else
2971     {
2972       if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2973         {
2974           flagcode_recordSuppressed (FLG_OWNEDTRANS);
2975         }
2976       else
2977         {
2978           if (alkind_isKept (tkind) && sRef_isNSLocalVar (tref))
2979             {
2980               ; /* okay */
2981             }
2982           else
2983             {
2984               voptgenerror
2985                 (FLG_OWNEDTRANS,
2986                  message ("Owned storage %q%q: %q",
2987                           sRef_unparseOpt (fref),
2988                           transferErrorMessage (transferType, tkind),
2989                           generateText (fexp, texp, tref, transferType)),
2990                  loc);
2991             }
2992         }
2993       
2994       if (transferType == TT_DOASSIGN)
2995         {
2996           /*
2997            ** alias kind unknown to suppress future messages
2998            */
2999           
3000           if (!ffix) { sRef_clearAliasKind (fref); }
3001         }
3002     }
3003 }
3004   
3005 static void
3006 checkFreshTransferAux (sRef fref, exprNode fexp, bool ffix,
3007                        sRef tref, exprNode texp, /*@unused@*/ bool tfix,
3008                        fileloc loc, transferKind transferType)
3009 {     
3010   alkind tkind = sRef_getAliasKind (tref);
3011
3012   /*
3013   ** error to return fresh as non-only
3014   */
3015
3016   if (transferType == TT_FCNRETURN
3017       && !(alkind_isOnly (tkind) || alkind_isNewRef (tkind)))
3018     {
3019       if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
3020         {
3021           flagcode_recordSuppressed (FLG_NEWREFTRANS);
3022         }
3023       else
3024         {
3025           if (alkind_isError (tkind))
3026             {
3027               if (!ffix) 
3028                 { 
3029                   sRef_killComplete (fref, loc); 
3030                 }
3031             }
3032           else if (alkind_isRefCounted (tkind))
3033             {
3034               if (optgenerror 
3035                   (FLG_NEWREFTRANS,
3036                    message
3037                    ("New reference returned without newref qualifier: %q",
3038                     generateText (fexp, texp, tref, transferType)),
3039                    loc))
3040                 {
3041                   sRef_showAliasInfo (fref);
3042                   sRef_killComplete (fref, loc);
3043                 }
3044               }
3045           else 
3046             {
3047               if (optgenerror 
3048                   (FLG_FRESHTRANS,
3049                    message ("Fresh storage %q (should be only): %q",
3050                             transferErrorMessage (transferType, tkind),
3051                             generateText (fexp, texp, tref, transferType)),
3052                    loc))
3053                 {
3054                   sRef_showAliasInfo (fref);
3055                   sRef_killComplete (fref, loc);
3056                 }
3057             }
3058         }
3059     }
3060   
3061   /*
3062   ** Okay to assign fresh to only, shared or unqualified.
3063   ** 
3064   ** should generate other errors? 
3065   */
3066
3067   if (alkind_isOnly (tkind))
3068     {
3069       if (transferType == TT_DOASSIGN && !sRef_isFileOrGlobalScope (tref))
3070         {
3071           if (!ffix) 
3072             { 
3073               if (!sRef_isNSLocalVar (tref))
3074                 {
3075                   sRef_setKeptComplete (fref, loc); 
3076                 }
3077             }
3078         }
3079       else
3080         {
3081           if (sRef_isConst (fref))
3082             {
3083               ;
3084             }
3085           else
3086             {
3087               if (!ffix) 
3088                 { 
3089                   sRef_killComplete (fref, loc); 
3090                 }
3091             }
3092         }
3093     }
3094   else if (alkind_isOwned (tkind))
3095     {
3096       if (!ffix) 
3097         { 
3098           sRef_setDependentComplete (fref, loc); 
3099         }
3100     }
3101   else if (alkind_isRefCounted (tkind)
3102            && (transferType == TT_FCNRETURN) && sRef_isFresh (fref))
3103     {
3104       if (!ffix) 
3105         { 
3106           sRef_killComplete (fref, loc); 
3107         }
3108     }
3109   else if (alkind_isKeep (tkind))
3110     {
3111       if (!ffix) 
3112         { 
3113           if (!sRef_isNSLocalVar (tref))
3114             {
3115               sRef_setKeptComplete (fref, loc); 
3116             }
3117         }
3118     }
3119   else if (alkind_isShared (tkind))
3120     {
3121       if (!ffix) { sRef_setShared (fref, loc); }
3122     }
3123   else if (alkind_isLocal (tkind) || alkind_isUnknown (tkind))
3124     {
3125       if (transferType == TT_DOASSIGN || transferType == TT_FCNRETURN)
3126         {
3127           /*
3128           ** local shares fresh.  Make it owned/dependent. 
3129           */
3130
3131           if (!tfix) 
3132             { 
3133               sRef_setOwned (tref, loc); 
3134             }
3135
3136           if (!ffix && !tfix) 
3137             { 
3138               sRef_setDependentComplete (fref, loc); 
3139             }
3140
3141           /* NO! sRef_clearAliasKind (fref); */
3142         }
3143       else 
3144         {
3145           if (context_getFlag (FLG_PASSUNKNOWN))
3146             {
3147               sRef_clearAliasKind (fref);
3148             }
3149         }
3150     }
3151   else
3152     {
3153       ;
3154     }
3155 }
3156
3157 static void
3158 checkTransferExposure (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
3159                        sRef tref, exprNode texp, bool tfix,
3160                        fileloc loc, 
3161                        transferKind transferType)
3162 {
3163   alkind fkind = sRef_getAliasKind (fref);
3164   alkind tkind = sRef_getAliasKind (tref);
3165   exkind tekind = sRef_getExKind (tref);
3166
3167   if (sRef_isObserver (fref) && ctype_isMutable (sRef_getType (fref)))
3168     {
3169       /*
3170       ** observer -> exposed or observer
3171       */
3172       
3173       /*
3174       ** observer -> temp is okay [NO!  really? only in function calls]
3175       */
3176
3177       if (sRef_isExposed (tref) || sRef_isObserver (tref)
3178           || alkind_isLocal (tkind))
3179         {
3180           /* okay */
3181           
3182           if ((transferType == TT_DOASSIGN) && alkind_isLocal (tkind))
3183             {
3184               if (!tfix) 
3185                 {
3186                   sRef_setAliasKindComplete (tref, fkind, loc); 
3187                 }
3188             }
3189         }
3190       else
3191         {
3192           if (transferType == TT_FCNRETURN 
3193               || transferType == TT_DOASSIGN
3194               || transferType == TT_FIELDASSIGN
3195               || transferType == TT_GLOBINIT)
3196             {
3197               bool hasError = FALSE;
3198               
3199               if (exprNode_isStringLiteral (fexp)
3200                   && transferType == TT_GLOBINIT)
3201                 {
3202                   hasError = optgenerror
3203                     (FLG_READONLYTRANS,
3204                      message ("Read-only string literal storage %q%q: %q",
3205                               sRef_unparseOpt (fref),
3206                               transferErrorExpMessage (transferType, tekind),
3207                               generateText (fexp, texp, tref, transferType)),
3208                      loc);
3209
3210                   sRef_setAliasKind (fref, AK_ERROR, fileloc_undefined);
3211                 }
3212               else 
3213                 {
3214                   if ((transferType == TT_DOASSIGN
3215                        || transferType == TT_FIELDASSIGN)
3216                       && (sRef_isNSLocalVar (tref)
3217                           || (exprNode_isStringLiteral (fexp)
3218                               && ctype_isRealArray (exprNode_getType (texp)))))
3219                     {
3220                       ; /* No error for local assignment or assignment
3221                            to static array (copies string). */
3222                     }
3223                   else
3224                     {
3225                       if (exprNode_isStringLiteral (fexp))
3226                         {
3227                           hasError = optgenerror 
3228                             (FLG_READONLYTRANS,
3229                              message
3230                              ("Read-only string literal storage %q%q: %q",
3231                               sRef_unparseOpt (fref),
3232                               transferErrorExpMessage (transferType, tekind),
3233                               generateText (fexp, texp, tref, transferType)),
3234                              loc);
3235                           
3236                         }
3237
3238                       if (!hasError)
3239                         {
3240                           hasError = optgenerror 
3241                             (FLG_OBSERVERTRANS,
3242                              message
3243                              ("Observer storage %q%q: %q",
3244                               sRef_unparseOpt (fref),
3245                               transferErrorExpMessage (transferType, tekind),
3246                               generateText (fexp, texp, tref, transferType)),
3247                              loc);
3248                         }
3249                     }
3250                 }
3251               
3252               if (hasError)
3253                 {
3254                   if (transferType != TT_GLOBINIT)
3255                     {
3256                       sRef_showExpInfo (fref);
3257                       sRef_setAliasKind (tref, AK_ERROR, loc);
3258                     }
3259                 }
3260               else 
3261                 {
3262                   if (transferType == TT_DOASSIGN && !tfix)
3263                     {
3264                       DPRINTF (("Setting unknown!"));
3265                       /* sRef_setAliasKind (tref, AK_ERROR, loc); */
3266                     }
3267                 }
3268             }
3269           else /* TT_FCNPASS */
3270             {
3271               llassert (transferType == TT_FCNPASS);
3272
3273               if (alkind_isTemp (tkind) 
3274                   || alkind_isDependent (tkind)
3275                   || alkind_isRefCounted (tkind))
3276                 {
3277                   ; /* okay */
3278                 }
3279               else 
3280                 {
3281                   if (!alkind_isError (tkind))
3282                     {
3283                       if (optgenerror 
3284                           (FLG_OBSERVERTRANS,
3285                            message ("Observer storage %q%q: %q",
3286                                     sRef_unparseOpt (fref),
3287                                     transferErrorMessage (transferType, tkind),
3288                                     generateText (fexp, texp, tref, transferType)),
3289                            loc))
3290                         {
3291                           sRef_showExpInfo (fref);
3292                           sRef_clearAliasState (fref, loc); 
3293                         }
3294                     }
3295                 }
3296             }
3297         }
3298     }
3299   else if (sRef_isExposed (fref) && ctype_isMutable (sRef_getType (fref)))
3300     {
3301       if (transferType == TT_FCNRETURN)
3302         {
3303           if (!(sRef_isExposed (tref) || sRef_isObserver (tref)
3304                 || sRef_isParam (fref)))
3305             {
3306               if (optgenerror
3307                   (FLG_EXPOSETRANS,
3308                    message ("Exposed storage %q%q: %q",
3309                             sRef_unparseOpt (fref),
3310                             transferErrorExpMessage (transferType, tekind),
3311                             generateText (fexp, texp, tref, transferType)),
3312                    loc))
3313                 {
3314                   sRef_showExpInfo (fref);
3315                 }
3316             }
3317         }
3318       else if (transferType == TT_FCNPASS)
3319         {
3320           if (!(sRef_isExposed (tref) 
3321                 || sRef_isObserver (tref)
3322                 || (alkind_isUnknown (tkind) 
3323                     || alkind_isDependent (tkind)
3324                     || alkind_isTemp (tkind)
3325                     || alkind_isKillRef (tkind)
3326                     || alkind_isRefCounted (tkind))))
3327             {
3328               if (alkind_isUnique (tkind) || alkind_isError (tkind))
3329                 {
3330                 }
3331               else 
3332                 {
3333                   if (optgenerror 
3334                       (FLG_EXPOSETRANS,
3335                        message ("Exposed storage %q%q: %q",
3336                                 sRef_unparseOpt (fref),
3337                                 transferErrorMessage (transferType, tkind),
3338                                 generateText (fexp, texp, tref, transferType)),
3339                        loc))
3340                     {
3341                       sRef_showExpInfo (fref);
3342                       sRef_clearAliasState (fref, loc); 
3343                     }
3344                 }
3345
3346             }
3347           else
3348             {
3349               ;
3350             }
3351         }
3352       else if (transferType == TT_DOASSIGN
3353                /* evans 2001-10-05: added TT_FIELDASSIGN: */
3354                || transferType == TT_FIELDASSIGN)
3355         {
3356           if (!(sRef_isExposed (tref) 
3357                 || !sRef_isCvar (tref)
3358                 || (alkind_isUnknown (tkind)
3359                     || alkind_isDependent (tkind)
3360                     || alkind_isRefCounted (tkind) 
3361                     || alkind_isNewRef (tkind)
3362                     || alkind_isFresh (tkind)
3363                     || alkind_isLocal (tkind))))
3364             {
3365               if (optgenerror 
3366                   (FLG_EXPOSETRANS,
3367                    message ("Exposed storage %q%q: %q",
3368                             sRef_unparseOpt (fref),
3369                             transferErrorExpMessage (transferType, tekind),
3370                             generateText (fexp, texp, tref, transferType)),
3371                    loc))
3372                 {
3373                   sRef_showExpInfo (fref);
3374                 }
3375             }
3376           if (!tfix) { sRef_setExposed (tref, loc); }
3377         }
3378       else
3379         {
3380           llassert (transferType == TT_GLOBPASS
3381                     || transferType == TT_GLOBRETURN
3382                     || transferType == TT_PARAMRETURN
3383                     || transferType == TT_LEAVETRANS
3384                     || transferType == TT_GLOBINIT);
3385         }
3386     }
3387   else
3388     {
3389       ;
3390     }
3391 }
3392
3393 /*
3394 ** returns TRUE if there is no error reported
3395 **
3396 ** if fixt, don't change tref (except if error reported.)
3397 ** if fixf, don't change fref (except if error reported.)
3398 */
3399
3400 static void
3401 checkTransferAux (exprNode fexp, /*@exposed@*/ sRef fref, bool ffix,
3402                   exprNode texp, /*@exposed@*/ sRef tref, bool tfix,
3403                   fileloc loc, transferKind transferType)
3404 {
3405   alkind fkind;
3406   alkind tkind;
3407   bool isassign = (transferType == TT_DOASSIGN);
3408   bool isfieldassign = (transferType == TT_FIELDASSIGN);
3409   bool iseitherassign = isassign || (transferType == TT_FIELDASSIGN);
3410   bool isfcnpass = (transferType == TT_FCNPASS);
3411   bool isfcnreturn = (transferType == TT_FCNRETURN);
3412
3413   setCodePoint ();
3414
3415   if (!ffix && !tfix)
3416     {
3417       setCodePoint ();
3418       checkTransferNullAux (fref, fexp, ffix, tref, texp, tfix, 
3419                             loc, transferType);
3420     }
3421
3422   if (isassign)
3423     {
3424       setCodePoint ();
3425       checkTransferAssignAux (fref, fexp, ffix, tref, texp, tfix,
3426                               loc, transferType);
3427     }
3428
3429   /*
3430   ** Check for definition 
3431   */
3432
3433   /*
3434   ** errors passing out params already detected in checkAnyCall
3435   */
3436
3437   if (!ffix && !tfix)
3438     {
3439       bool defok = TRUE;
3440
3441       if (!iseitherassign 
3442           || (!sRef_isNSLocalVar (tref) 
3443               && (sRef_isAnyDefined (tref) || !sRef_stateKnown (tref))))
3444         {
3445           setCodePoint ();
3446
3447           if (!ynm_toBoolRelaxed 
3448               (checkCompletelyDefined (fexp, fref, fref,
3449                                        texp, tref,
3450                                        TRUE, FALSE, FALSE, 
3451                                        loc, transferType, 0, TRUE)))
3452             {
3453               defok = FALSE;
3454             }
3455         }
3456
3457       setCodePoint ();
3458       
3459       if (defok && iseitherassign)
3460         {
3461           sRef_setDefState (tref, sRef_getDefState (fref), loc);
3462         }
3463     }
3464
3465   /*
3466   ** check exposure
3467   */
3468
3469   setCodePoint ();
3470   checkTransferExposure (fref, fexp, ffix, tref, texp, tfix, 
3471                          loc, transferType);
3472
3473   fkind = sRef_getAliasKind (fref);
3474   tkind = sRef_getAliasKind (tref);
3475
3476   /*
3477   ** check aliasing
3478   */
3479
3480   if (alkind_isOnly (fkind))
3481     {
3482       setCodePoint ();
3483       checkOnlyTransferAux (fref, fexp, ffix,
3484                             tref, texp, tfix, 
3485                             loc, transferType);
3486     }
3487   else if (alkind_isFresh (fkind))
3488     {
3489       setCodePoint ();
3490       checkFreshTransferAux (fref, fexp, ffix,
3491                              tref, texp, tfix,
3492                              loc, transferType);
3493     }
3494   else if (alkind_isOwned (fkind))
3495     {
3496       setCodePoint ();
3497       checkOwnedTransferAux (fref, fexp, ffix,
3498                              tref, texp, tfix,
3499                              loc, transferType);
3500     }
3501   else if (alkind_isDependent (fkind))
3502     {
3503       setCodePoint ();
3504       if (isfcnreturn && 
3505           (sRef_isExposed (tref) || sRef_isObserver (tref)))
3506         {
3507           ; /* okay */
3508         }
3509       else if ((alkind_isOnly (tkind) || alkind_isKeep (tkind)
3510                 || alkind_isOwned (tkind))
3511                || (!isfcnpass && alkind_isTemp (tkind)))
3512         {
3513           bool error = TRUE;
3514
3515           if (sRef_isLocalVar (fref))
3516             {
3517               sRef depRef = dependentReference (fref);
3518
3519               if (sRef_isValid (depRef) && sRef_isLocalVar (depRef))
3520                 {
3521                   error = FALSE;
3522                   sRef_kill (depRef, loc);
3523                   sRef_kill (fref, loc);
3524                 }
3525
3526             }
3527
3528           if (isfieldassign)
3529             {
3530               error = FALSE;
3531             }
3532
3533           if (canLoseLocalReference (fref, loc))
3534             {
3535               ;
3536             }
3537           else
3538             {
3539               if (error &&
3540                   (optgenerror 
3541                    (FLG_DEPENDENTTRANS,
3542                     message ("%s storage %q%q: %q",
3543                              alkind_capName (fkind),
3544                              sRef_unparseOpt (fref),
3545                              transferErrorMessage (transferType, tkind),
3546                              generateText (fexp, texp, tref, transferType)),
3547                     loc)))
3548                 {
3549                   DPRINTF (("Here: %s / %s", 
3550                             sRef_unparseFull (fref),
3551                             sRef_unparseFull (tref)));
3552
3553                   sRef_showAliasInfo (fref);
3554                 }
3555             }
3556         }
3557       else 
3558         {
3559           if (isassign && (alkind_isFresh (tkind) || alkind_isLocal (tkind)))
3560             {
3561               if (!tfix && !ffix)
3562                 {
3563                   sRef_setDependent (tref, loc);
3564                 }
3565             }
3566         }
3567     }
3568   else if (alkind_isShared (fkind))
3569     {
3570       setCodePoint ();
3571       /*
3572       ** xxx <- shared
3573       */
3574
3575       if (alkind_isOnly (tkind) 
3576           || (!isfcnpass 
3577               && (!(sRef_isObserver (tref) || sRef_isExposed (tref)) 
3578                   && alkind_isTemp (tkind))))
3579         {
3580           if (optgenerror
3581               (FLG_SHAREDTRANS,
3582                message ("%s storage %q%q: %q",
3583                         alkind_capName (fkind),
3584                         sRef_unparseOpt (fref),
3585                         transferErrorMessage (transferType, tkind),
3586                         generateText (fexp, texp, tref, transferType)),
3587                loc))
3588             {
3589               sRef_showAliasInfo (fref);
3590             }
3591         }
3592       else 
3593         {
3594           if (alkind_isFresh (tkind) || alkind_isLocal (tkind))
3595             {
3596               sRef_setShared (tref, loc);
3597             }
3598         }
3599     }
3600   else if (alkind_isKeep (fkind))
3601     {
3602       setCodePoint ();
3603
3604       if (alkind_isKeep (tkind) 
3605           || alkind_isLocal (tkind)
3606           || (isfcnreturn && sRef_isExposed (tref))
3607           || (iseitherassign 
3608               && (alkind_isOnly (tkind) || alkind_isOwned (tkind))))
3609         {
3610           sRef_setKept (fref, loc);
3611         }
3612       else if (isfcnpass 
3613                && (alkind_isTemp (tkind) || alkind_isOwned (tkind)))
3614         {
3615           ;
3616         }
3617       else 
3618         {
3619           if (!alkind_isError (tkind))
3620             {
3621               if (optgenerror
3622                   (FLG_KEEPTRANS,
3623                    message ("%s storage %q: %q",
3624                             alkind_capName (fkind),
3625                             transferErrorMessage (transferType, tkind),
3626                             generateText (fexp, texp, tref, transferType)),
3627                    loc))
3628                 {
3629                   sRef_showAliasInfo (fref);
3630                 }
3631             }
3632         }
3633     }
3634   else if (alkind_isTemp (fkind) || alkind_isKept (fkind))
3635     {
3636       /*
3637       ** xxx <- temp
3638       */
3639       
3640       if (alkind_isOnly (tkind)
3641           || alkind_isShared (tkind) 
3642           || (alkind_isTemp (fkind)
3643               && !isfcnreturn && alkind_isDependent (tkind))
3644           || alkind_isOwned (tkind)
3645           || alkind_isKeep (tkind))
3646         {
3647           if (!exprNode_isNullValue (fexp)
3648               && (ctype_isMutable (exprNode_getType (fexp))
3649                   || (ctype_isArray (exprNode_getType (fexp))
3650                       && sRef_isParam (fref)))
3651               && (!iseitherassign || sRef_isReference (tref)))
3652             {
3653               if (sRef_isThroughArrayFetch (fref))
3654                 {
3655                   if (optgenerror2
3656                       (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3657                        FLG_STRICTUSERELEASED,
3658                        message ("%s storage %q%q: %q",
3659                                 alkind_capName (fkind),
3660                                 sRef_unparseOpt (fref),
3661                                 transferErrorMessage (transferType, tkind),
3662                                 generateText (fexp, texp, tref, transferType)),
3663                        loc))
3664                     {
3665                       sRef_showAliasInfo (fref);
3666                     }
3667                 }
3668               else
3669                 {
3670                   if (optgenerror
3671                       (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3672                        message ("%s storage %q%q: %q",
3673                                 alkind_capName (fkind),
3674                                 sRef_unparseOpt (fref),
3675                                 transferErrorMessage (transferType, tkind),
3676                                 generateText (fexp, texp, tref, transferType)),
3677                        loc))
3678                     {
3679                       sRef_showAliasInfo (fref);
3680                     }
3681                 }
3682             }
3683         }
3684     }
3685   else if (alkind_isRefCounted (fkind) || alkind_isKillRef (fkind))
3686     {
3687       if (alkind_isNewRef (tkind))
3688         {
3689           /*
3690           ** check that the refs field has been modified
3691           */
3692
3693           if (!sRef_isConst (fref))
3694             {
3695               voptgenerror 
3696                 (FLG_REFCOUNTTRANS,
3697                  message ("Reference counted storage returned without modifying "
3698                           "reference count: %s",
3699                           exprNode_unparse (fexp)),
3700                  loc);
3701             }
3702         }
3703       else if (iseitherassign)
3704         {
3705           if (alkind_isRefCounted (fkind))
3706             {
3707               if (!sRef_isLocalVar (tref))
3708                 {
3709                   vgenhinterror 
3710                     (FLG_REFCOUNTTRANS,
3711                      message 
3712                      ("Assignment to non-local from reference counted storage: %s",
3713                       exprNode_unparse (fexp)),
3714                      cstring_makeLiteral 
3715                      ("Reference counted storage should call a function returning "
3716                       "a newref instead of direct assignments."),
3717                      loc);
3718                 }
3719               else
3720                 {
3721                   ;
3722                 }
3723             }
3724         }
3725       else /* fcnpass */
3726         {
3727           if (alkind_isRefCounted (tkind) || alkind_isTemp (tkind))
3728             {
3729               /* okay --- no change in state */
3730             }
3731           else if (alkind_isKillRef (tkind))
3732             {
3733               if (!ffix && !tfix && !(transferType == TT_FCNRETURN))
3734                 { 
3735                   sRef_killComplete (fref, loc); 
3736                 }
3737             }
3738           else 
3739             {
3740               if (!alkind_isError (tkind))
3741                 {
3742                   voptgenerror
3743                     (FLG_REFCOUNTTRANS,
3744                      message ("Reference counted storage %q: %q",
3745                               transferErrorMessage (transferType, tkind),
3746                               generateText (fexp, texp, tref, transferType)),
3747                      loc);
3748                 }
3749             }
3750         }
3751     }
3752   else
3753     {
3754       ;
3755     }
3756
3757   setCodePoint ();
3758   
3759   if (alkind_isOnly (tkind) || alkind_isKeep (tkind))
3760     {
3761       if (sRef_isAddress (fref))
3762         {
3763           voptgenerror
3764             (FLG_IMMEDIATETRANS,
3765              message ("Immediate address %q %q: %q", 
3766                       sRef_unparse (fref),
3767                       transferErrorMessage (transferType, tkind),
3768                       generateText (fexp, texp, tref, transferType)),
3769              loc);
3770           
3771           sRef_setAliasKind (fref, AK_ERROR, loc);
3772         }
3773       else 
3774         {
3775           if ((alkind_isUnknown (fkind) || alkind_isStatic (fkind))
3776               && !sRef_isDefinitelyNull (fref)
3777               && (!ffix && !tfix)
3778               && (!exprNode_isNullValue (fexp)))
3779             {
3780               flagcode errkind = alkind_isStatic (fkind) 
3781                 ? FLG_STATICTRANS : FLG_UNKNOWNTRANS;
3782
3783               if (transferType == TT_GLOBINIT)
3784                 {
3785                   if (errkind == FLG_STATICTRANS)
3786                     {
3787                       errkind = FLG_STATICINITTRANS;
3788                     }
3789                   else
3790                     {
3791                       errkind = FLG_UNKNOWNINITTRANS;
3792                     }
3793                 }
3794
3795               if (optgenerror 
3796                   (errkind,
3797                    message ("%s storage %s %q: %q",
3798                             alkind_capName (fkind),
3799                             exprNode_unparse (fexp),
3800                             transferErrorMessage (transferType, tkind),
3801                             generateText (fexp, texp, tref, transferType)),
3802                    loc))
3803                 {
3804                   sRef_showAliasInfo (fref);
3805                 }
3806             }
3807         }
3808       
3809       /* don't kill shared to suppress future messages */
3810       if (!alkind_isShared (fkind))
3811         {
3812           if (isassign)
3813             {
3814               if (!ffix) 
3815                 {
3816                   /*< yuk! should do this in aliasaux >*/
3817                    
3818                   if (!sRef_isNSLocalVar (tref) && !sRef_sameName (fref, tref))
3819                     {
3820                       if (!tfix)
3821                         {
3822                           sRef_setKeptComplete (fref, loc);
3823                         }
3824                       else
3825                         {
3826                           sRef_setKept (fref, loc);
3827                         }
3828                     }
3829                 }
3830             }
3831           else
3832             {
3833               if (!ffix) 
3834                 {
3835                   if (!tfix)
3836                     {
3837                       if (alkind_isKeep (tkind))
3838                         {
3839                           sRef_setKeptComplete (fref, loc);
3840                         }
3841                       else
3842                         {
3843                           sRef_killComplete (fref, loc); 
3844                         }
3845                     }
3846                   else
3847                     {
3848                       if (alkind_isKeep (tkind))
3849                         {
3850                           sRef_setKept (fref, loc);
3851                         }
3852                       else
3853                         {
3854                           sRef_kill (fref, loc);
3855                         }
3856                     }
3857                 }
3858             }
3859         }
3860     }
3861   else if (alkind_isOwned (tkind))
3862     {
3863       /* don't kill shared to suppress future messages */
3864       if (!alkind_isShared (fkind)) 
3865         {
3866           if (!isassign 
3867               || !sRef_sameName (fref, tref)) /* result of return parameter */
3868             {
3869               if (!ffix)
3870                 {
3871                   if (!tfix)
3872                     {
3873                       sRef_setDependentComplete (fref, loc);
3874                     }
3875                   else
3876                     {
3877                       sRef_setDependent (fref, loc);
3878                     }
3879                 }
3880             }
3881         }
3882     }
3883   else if (alkind_isShared (tkind))
3884     {
3885       if (alkind_isFresh (fkind) || alkind_isLocal (fkind))
3886         {
3887           if (!ffix) 
3888             {
3889               sRef_setShared (fref, loc);
3890             }
3891         }
3892     }
3893   else if (alkind_isUnknown (tkind) && context_getFlag (FLG_MEMIMPLICIT))
3894     {
3895       if (alkind_isDependent (fkind))
3896         {
3897           if (!exprNode_isNullValue (fexp)
3898               && ctype_isMutable (exprNode_getType (fexp))
3899               && (!iseitherassign || sRef_isReference (tref)))
3900             {
3901               if (transferChecks_canLoseReference (fref, loc))
3902                 {
3903                   ;
3904                 }
3905               else
3906                 {
3907                   if (optgenerror
3908                       (FLG_DEPENDENTTRANS,
3909                        message ("%s storage %q%q: %q",
3910                                 alkind_capName (fkind),
3911                                 sRef_unparseOpt (fref),
3912                                 transferErrorMessage (transferType, tkind),
3913                                 generateText (fexp, texp, tref, transferType)),
3914                        loc))
3915                     {
3916                       DPRINTF (("Here: %s / %s", sRef_unparseFull (fref),
3917                                 sRef_unparseFull (tref)));
3918                       sRef_showAliasInfo (fref);
3919                     }
3920                 }
3921             }
3922         }
3923     }
3924   else if (alkind_isNewRef (tkind))
3925     {
3926       if (!ffix && !tfix)
3927         { 
3928           sRef_killComplete (fref, loc);  
3929         }
3930     }
3931   else if (alkind_isKillRef (tkind))
3932     {
3933       if (transferType == TT_FCNRETURN)
3934         {
3935           if (sRef_isNewRef (fref))
3936             {
3937               if (optgenerror
3938                   (FLG_REFCOUNTTRANS,
3939                    message ("New reference returned as temp reference: %q",
3940                             generateText (fexp, texp, tref, transferType)),
3941                    loc))
3942                 {
3943                   sRef_showAliasInfo (fref);
3944                 }
3945               }
3946         }
3947       else
3948         {
3949           if (sRef_isNewRef (fref))
3950             {
3951               sRef_killComplete (fref, loc);
3952             }
3953           else 
3954             {
3955               if (sRef_isRefCounted (fref) 
3956                   && sRef_isCvar (fref)
3957                   && !sRef_isLocalVar (fref))
3958                 {
3959                   if (optgenerror
3960                       (FLG_REFCOUNTTRANS,
3961                        message 
3962                        ("External reference counted storage released: %q",
3963                         generateText (fexp, texp, tref, transferType)),
3964                        loc))
3965                     {
3966                       sRef_showAliasInfo (fref);
3967                     }
3968                 }
3969             }
3970         }
3971           
3972     }
3973   else
3974     {
3975       ;
3976     }
3977
3978   setCodePoint ();
3979 }
3980
3981 static void
3982 checkMetaStateConsistent (/*@exposed@*/ sRef fref, sRef tref, 
3983                           fileloc loc, /*@unused@*/ transferKind transferType)
3984 {
3985   /*
3986   ** Checks if it is consistent to leave storage marked as tref in state of fref.
3987   */
3988
3989   valueTable fvalues = sRef_getValueTable (fref);
3990   valueTable tvalues = sRef_getValueTable (tref);
3991   
3992   DPRINTF (("Metastate consistent: %s => %s",
3993             sRef_unparseFull (fref),
3994             sRef_unparseFull (tref)));
3995   
3996   if (valueTable_isUndefined (tvalues) || valueTable_isUndefined (fvalues)) {
3997     /* Cannot check without value tables.  An error was already detected. */
3998     DPRINTF (("No value table: %s / %s",
3999               bool_unparse (valueTable_isUndefined (tvalues)),
4000               bool_unparse (valueTable_isUndefined (fvalues))));
4001     return;
4002   }
4003
4004   valueTable_elements (fvalues, fkey, fval) {
4005     stateValue tval;
4006     metaStateInfo minfo;
4007
4008     DPRINTF (("Transfer: %s", fkey));
4009     tval = valueTable_lookup (tvalues, fkey);
4010     minfo = context_lookupMetaStateInfo (fkey);
4011
4012     if (!stateValue_isDefined (tval)) 
4013       {
4014         if (ctype_isUnknown (sRef_getType (fref)))
4015           {
4016             ; /* Okay, put in default values without knowing type */
4017           }
4018         else
4019           {
4020             DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
4021                       sRef_unparseFull (tref),
4022                       fkey));
4023           }
4024       }
4025     else
4026       {
4027         llassert (metaStateInfo_isDefined (minfo));
4028         
4029         if (stateValue_isError (fval) || stateValue_isError (tval))
4030           {
4031             ;
4032           }
4033         else if (sRef_isDefinitelyNull (fref)
4034                  || usymtab_isDefinitelyNull (fref))
4035           {
4036             ; /* No errors for null values in state transfers. */
4037           }
4038         
4039         else
4040           {
4041             stateCombinationTable sctable = metaStateInfo_getTransferTable (minfo);
4042             cstring msg = cstring_undefined;
4043             int nval = stateCombinationTable_lookup (sctable, 
4044                                                      stateValue_getValue (fval), 
4045                                                      stateValue_getValue (tval), 
4046                                                      &msg);
4047             
4048             if (nval == stateValue_error)
4049               {
4050                 if (transferType == TT_LEAVETRANS)
4051                   {
4052                     BADBRANCH;
4053                   }
4054                 else if (transferType == TT_GLOBRETURN)
4055                   {
4056                     if (optgenerror 
4057                         (FLG_STATETRANSFER,
4058                          message
4059                          ("Function returns with global %q in inconsistent state (%q is %q, should be %q)%q",
4060                           sRef_unparse (sRef_getRootBase (fref)),
4061                           sRef_unparse (fref),
4062                           stateValue_unparseValue (fval, minfo),
4063                           stateValue_unparseValue (tval, minfo),
4064                           cstring_isDefined (msg) 
4065                           ? message (": %s", msg) : cstring_undefined),
4066                          loc))
4067                       {
4068                         sRef_showMetaStateInfo (fref, fkey);
4069                       }             
4070                   }
4071                 else if (transferType == TT_GLOBPASS)
4072                   {
4073                     if (optgenerror 
4074                         (FLG_STATETRANSFER,
4075                          message
4076                          ("Function called with global %q in inconsistent state (%q is %q, should be %q)%q",
4077                           sRef_unparse (sRef_getRootBase (fref)),
4078                           stateValue_unparseValue (fval, minfo),
4079                           sRef_unparse (fref),
4080                           stateValue_unparseValue (tval, minfo),
4081                           cstring_isDefined (msg) 
4082                           ? message (": %s", msg) : cstring_undefined),
4083                          loc))
4084                       {
4085                         sRef_showMetaStateInfo (fref, fkey);
4086                       }             
4087                   }
4088                 else if (transferType == TT_PARAMRETURN)
4089                   {
4090                     if (optgenerror 
4091                         (FLG_STATETRANSFER,
4092                          message
4093                          ("Function returns with parameter %q in inconsistent state (%q is %q, should be %q)%q",
4094                           sRef_unparse (sRef_getRootBase (fref)),
4095                           sRef_unparse (fref),                  
4096                           stateValue_unparseValue (fval, minfo),
4097                           stateValue_unparseValue (tval, minfo),
4098                           cstring_isDefined (msg) 
4099                           ? message (": %s", msg) : cstring_undefined),
4100                          loc))
4101                       {
4102                         sRef_showMetaStateInfo (fref, fkey);
4103                       }
4104                   }
4105                 else
4106                   {
4107                     if (optgenerror 
4108                         (FLG_STATETRANSFER,
4109                          message
4110                          ("Invalid transfer from %q %x to %q (%q)%q",
4111                           stateValue_unparseValue (fval, minfo),
4112                           sRef_unparse (fref),
4113                           stateValue_unparseValue (tval, minfo),
4114                           sRef_unparse (tref),
4115                           cstring_isDefined (msg) 
4116                           ? message (": %s", msg) : cstring_undefined),
4117                          loc))
4118                       {
4119                         sRef_showMetaStateInfo (fref, fkey);
4120                       }
4121                   }
4122
4123               }
4124                     
4125             if (stateValue_getValue (fval) != nval)
4126               {
4127                 stateValue_updateValueLoc (fval, nval, loc);
4128               }
4129           }
4130       }
4131     
4132     DPRINTF (("Transfer: %s %s -> %s",
4133               fkey, stateValue_unparse (fval), stateValue_unparse (tval)));
4134   } end_valueTable_elements ;
4135 }
4136
4137 static void
4138 checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref, 
4139                         exprNode fcn,
4140                         fileloc loc, transferKind transferType)
4141 {
4142   valueTable fvalues = sRef_getValueTable (fref);
4143   valueTable tvalues = sRef_getValueTable (tref);
4144
4145   DPRINTF (("Metastate transfer: from %s", exprNode_unparse (fexp)));
4146   
4147   DPRINTF (("Metastate transfer: %s => %s",
4148             sRef_unparseFull (fref),
4149             sRef_unparseFull (tref)));
4150
4151   if (valueTable_isUndefined (tvalues) || valueTable_isUndefined (fvalues)) {
4152     /* Cannot check without value tables.  An error was already detected. */
4153     DPRINTF (("No value table: %s / %s",
4154               bool_unparse (valueTable_isUndefined (tvalues)),
4155               bool_unparse (valueTable_isUndefined (fvalues))));
4156     return;
4157   }
4158
4159   valueTable_elements (fvalues, fkey, fval) {
4160     stateValue tval;
4161     metaStateInfo minfo;
4162     stateCombinationTable sctable;
4163     cstring msg;
4164     int nval;
4165
4166     DPRINTF (("Transfer: %s", fkey));
4167     tval = valueTable_lookup (tvalues, fkey);
4168     minfo = context_lookupMetaStateInfo (fkey);
4169
4170     if (!stateValue_isDefined (tval)) 
4171       {
4172         if (ctype_isUnknown (sRef_getType (fref)))
4173           {
4174             ; /* Okay, put in default values without knowing type */
4175           }
4176         else
4177           {
4178             DPRINTF (("Metastate transfer: %s => %s",
4179                       exprNode_unparse (fexp), exprNode_unparse (texp)));
4180             DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
4181                       sRef_unparseFull (tref),
4182                       fkey));
4183           }
4184       }
4185     else
4186       {
4187         llassert (metaStateInfo_isDefined (minfo));
4188         
4189         if (stateValue_isError (fval))
4190           {
4191             ;
4192           }
4193         else if (stateValue_isError (tval))
4194           {
4195             if (sRef_isLocalVar (tref) && transferType == TT_DOASSIGN)
4196               {
4197                 /* Local assignments just replace state. */
4198                 stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
4199                 DPRINTF (("Update: %s", stateValue_unparse (tval)));
4200               }
4201             else if (transferType == TT_FCNRETURN)
4202               {
4203                 ; /* Returning from an unannotated function */
4204               }
4205             else
4206               {
4207                 DPRINTF (("Transfer to error: %s / %s", sRef_unparseFull (tref),
4208                           transferType_unparse (transferType)));
4209               }
4210           }
4211         else 
4212           {
4213             DPRINTF (("Check: %s / %s / %s / %s", fkey,
4214                       metaStateInfo_unparse (minfo),
4215                       stateValue_unparse (fval),
4216                       stateValue_unparse (tval)));
4217             
4218             sctable = metaStateInfo_getTransferTable (minfo);
4219             msg = cstring_undefined;
4220             
4221             nval = stateCombinationTable_lookup (sctable, 
4222                                                  stateValue_getValue (fval), 
4223                                                  stateValue_getValue (tval), 
4224                                                  &msg);
4225             
4226             if (transferType == TT_DOASSIGN && sRef_isLocalVar (tref))
4227               {
4228                 /* Local assignments just replace state. */
4229                 DPRINTF (("No transfer error assigning to local: %s", msg));
4230                 stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
4231                 DPRINTF (("Update: %s", stateValue_unparse (tval)));
4232               }
4233             else
4234               {
4235                 if (nval == stateValue_error)
4236                   {
4237                     if (optgenerror 
4238                         (FLG_STATETRANSFER,
4239                          message
4240                          ("Invalid transfer from %q %x to %q%q: %q",
4241                           stateValue_unparseValue (fval, minfo),
4242                           sRef_unparse (fref),
4243                           stateValue_unparseValue (tval, minfo),
4244                           cstring_isDefined (msg) 
4245                           ? message (" (%s)", msg) : cstring_undefined,
4246                           transferErrorExcerpt (transferType, fexp, texp, fcn)),
4247                          loc))
4248                       {
4249                         sRef_showMetaStateInfo (fref, fkey);
4250                         sRef_showMetaStateInfo (tref, fkey);
4251                       }
4252                     else
4253                       {
4254                         DPRINTF (("Suppressed transfer error: %s", msg));
4255                       }
4256                   }
4257                 else
4258                   {
4259                     if (transferType == TT_FCNRETURN)
4260                       {
4261                         /*
4262                         ** Returning this reference from a function, mark this reference
4263                         ** so no lost reference errors are returned.
4264                         */ 
4265
4266                         stateValue_updateValueLoc (fval, stateValue_error, loc);
4267                       }
4268                     else if (stateValue_getValue (fval) != nval)
4269                       {
4270                         stateValue_updateValueLoc (fval, nval, loc);
4271                       }
4272                     else
4273                       {
4274                         ;
4275                       }
4276                   }
4277               }
4278           }
4279       }
4280     
4281     DPRINTF (("Transfer: %s %s -> %s",
4282               fkey, stateValue_unparse (fval), stateValue_unparse (tval)));
4283   } end_valueTable_elements ;
4284 }
4285
4286 /*
4287 ** assigns fexp := tref or passes fexp as a parameter, or returns fexp.
4288 **
4289 ** For assignments, sets alias and definition state accordingly.
4290 */
4291
4292 static void
4293 checkTransfer (exprNode fexp, /*@dependent@*/ sRef fref, 
4294                exprNode texp, /*@dependent@*/ sRef tref, 
4295                exprNode fcn,
4296                fileloc loc, transferKind transferType)
4297 {
4298   setCodePoint ();
4299
4300   if (context_inProtectVars ())
4301     {
4302       return;
4303     }
4304   
4305   DPRINTF (("Check transfer: %s => %s",
4306             sRef_unparse (fref),
4307             sRef_unparse (tref)));
4308   DPRINTF (("Check transfer: %s => %s",
4309             exprNode_unparse (fexp),
4310             exprNode_unparse (texp)));
4311
4312   checkMetaStateTransfer (fexp, fref, texp, tref, fcn,
4313                           loc, transferType);
4314
4315   /*
4316   ** for local references, we need to check
4317   ** the transfer for all possible aliases.
4318   */
4319
4320   if (sRef_isLocalVar (tref) && transferType != TT_DOASSIGN)
4321     {    
4322       sRefSet alias = usymtab_allAliases (tref);
4323
4324       sRefSet_realElements (alias, atref)
4325         {
4326           sRef abase = sRef_getRootBase (atref);
4327
4328           if (sRef_isKnown (atref)
4329               && !sRef_isLocalVar (abase) 
4330               && !sRef_isExternal (abase))
4331             {
4332               atref = sRef_updateSref (atref);
4333
4334               if (sRef_hasName (atref))
4335                 {
4336                   if (!sRef_isNew (atref) 
4337                       && !sRef_sameName (tref, atref))
4338                     {
4339                       context_setAliasAnnote (atref, tref);
4340                     }
4341                   
4342                   checkTransferAux (fexp, fref, TRUE, 
4343                                     texp, atref, FALSE,
4344                                     loc, transferType);
4345                   
4346                   context_clearAliasAnnote ();
4347                 }
4348             }
4349         } end_sRefSet_realElements;
4350
4351       sRefSet_free (alias);
4352     }
4353
4354   if (sRef_isLocalVar (fref))
4355     {    
4356       sRefSet alias = usymtab_allAliases (fref);
4357
4358       sRefSet_realElements (alias, afref)
4359         {
4360           sRef abase = sRef_getRootBase (afref);
4361
4362           if (sRef_isKnown (afref) 
4363               && !sRef_isLocalVar (abase)
4364               && !sRef_isExternal (abase))
4365             {
4366               afref = sRef_updateSref (afref);
4367
4368               if (sRef_hasName (afref))
4369                 {
4370                   if (!sRef_isNew (afref) 
4371                       && !sRef_sameName (afref, fref))
4372                     {
4373                       context_setAliasAnnote (afref, fref);
4374                     }
4375                   
4376                   checkTransferAux (fexp, afref, FALSE,
4377                                     texp, tref, TRUE,
4378                                     loc, transferType);
4379                   
4380                   context_clearAliasAnnote ();
4381                 }
4382             }
4383         } end_sRefSet_realElements;
4384
4385       sRefSet_free (alias);
4386     }
4387   
4388   setCodePoint ();
4389   checkTransferAux (fexp, fref, FALSE, texp, tref, FALSE, 
4390                     loc, transferType);
4391   setCodePoint ();  
4392 }
4393
4394 static /*@exposed@*/ sRef 
4395   dependentReference (sRef sr)
4396 {
4397   sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4398
4399   DPRINTF (("Dependent reference: %s", sRef_unparse (sr)));
4400   DPRINTF (("Aliases: %s", sRefSet_unparse (ab)));
4401
4402   /*
4403   ** If there is a local variable that aliases sr, then there is no
4404   ** error.  Make the local an only.
4405   */
4406   
4407   if (!sRefSet_isEmpty (ab))
4408     {
4409       sRef res = sRef_undefined;
4410
4411       DPRINTF (("Here we are!"));
4412
4413       /*
4414       ** make one an only, others alias it
4415       */
4416                   
4417       sRefSet_realElements (ab, current)
4418         {
4419           if (sRef_isOwned (current))
4420             {
4421               res = current; 
4422               break;
4423             }
4424         } end_sRefSet_realElements;
4425
4426       if (sRef_isInvalid (res))
4427         {
4428           /* 
4429           ** evans - 2001-03-24
4430           ** No owned element, just choose one! 
4431           ** (Any reason for preference?)
4432           */
4433
4434           res = sRefSet_choose (ab);
4435         }
4436
4437       sRefSet_free (ab);
4438       return res;
4439     }
4440
4441   return sRef_undefined;
4442 }
4443
4444 bool transferChecks_canLoseReference (/*@dependent@*/ sRef sr, fileloc loc)
4445 {
4446   bool gotone = FALSE;
4447   sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4448     
4449   /*
4450   ** if there is a local variable that aliases sr, then there is no
4451   ** error.  Make the local an only.
4452   */
4453   
4454   if (!sRefSet_isEmpty (ab))
4455     {
4456       /*
4457       ** make one an only, others alias it
4458       */
4459       
4460       sRefSet_realElements (ab, current)
4461         {
4462           sRef_setLastReference (current, sr, loc);
4463           gotone = TRUE;
4464           break;
4465         } end_sRefSet_realElements;
4466
4467       sRefSet_free (ab);
4468     }
4469
4470   return gotone;
4471 }
4472
4473 bool canLoseLocalReference (/*@dependent@*/ sRef sr, fileloc loc)
4474 {
4475   bool gotone = FALSE;
4476   sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4477     
4478   /*
4479   ** if there is a local variable that aliases sr, then there is no
4480   ** error.  Make the local an only.
4481   */
4482   
4483   if (!sRefSet_isEmpty (ab))
4484     {
4485       /*
4486       ** make one an only, others alias it
4487       */
4488       
4489       sRefSet_realElements (ab, current)
4490         {
4491           if (sRef_isRealLocalVar (sRef_getRootBase (current)))
4492             {
4493               sRef_setLastReference (current, sr, loc);
4494               gotone = TRUE;
4495               break;
4496             }
4497         } end_sRefSet_realElements;
4498
4499       sRefSet_free (ab);
4500     }
4501
4502   return gotone;
4503 }
This page took 0.406044 seconds and 3 git commands to generate.