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