]> andersk Git - splint.git/blob - src/transferChecks.c
Updated copyright date.
[splint.git] / src / transferChecks.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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://www.splint.org
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 Splint.",
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                       /* evans 2001-08-21: added this branch for global returns */
1209                       else if (transferType == TT_GLOBRETURN)
1210                         {
1211                           voptgenerror 
1212                             (FLG_UNIONDEF,
1213                              message ("Union %q reachable from global %q has "
1214                                       "no defined field",
1215                                       sRef_unparse (fref),
1216                                       sRef_unparse (sRef_getRootBase (fref))),
1217                              loc);
1218                         }
1219                       else if (transferType == TT_DOASSIGN
1220                                || transferType == TT_FIELDASSIGN
1221                                || transferType == TT_GLOBINIT)
1222                         {
1223                           ; /* no error */
1224                         }
1225                       else
1226                         {
1227                           voptgenerror 
1228                             (FLG_UNIONDEF,
1229                              message ("%s union %q has no defined field",
1230                                       transferType_unparse (transferType),
1231                                       sRef_unparse (fref)),
1232                              loc);
1233                         }
1234                     }
1235                   isOk = FALSE;
1236                 }
1237               
1238               cstringSList_free (goodFields);
1239               return ynm_fromBool (!report || isOk);
1240             }
1241         }
1242     }
1243   else
1244     {
1245       ;
1246     }
1247
1248   return YES;
1249 }
1250
1251 /*
1252 ** fref is being free'd
1253 */
1254
1255 typedef enum {
1256   DSC_GLOB, DSC_LOCAL, DSC_PARAM, DSC_STRUCT
1257   } dscCode;
1258
1259 static /*@observer@*/ cstring dscCode_unparse (dscCode desc) /*@*/
1260 {
1261   switch (desc)
1262     {
1263     case DSC_GLOB:
1264       return cstring_makeLiteralTemp ("killed global");
1265     case DSC_LOCAL:
1266       return cstring_makeLiteralTemp ("variable declared in this scope");
1267     case DSC_PARAM:
1268       return cstring_makeLiteralTemp ("released storage");
1269     case DSC_STRUCT:
1270       return cstring_makeLiteralTemp ("released structure parameter");
1271     }
1272
1273   BADEXIT;
1274 }
1275
1276 static bool 
1277   checkCompletelyDestroyed (exprNode p_fexp, sRef p_fref, bool p_topLevel, 
1278                             fileloc p_loc, int p_depth, dscCode p_desc,
1279                             bool p_hideErrors);
1280
1281 bool checkGlobalDestroyed (sRef fref, fileloc loc)
1282 {
1283   return (checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1284                                     loc, 0, DSC_GLOB, FALSE));
1285 }
1286
1287 void checkLocalDestroyed (sRef fref, fileloc loc)
1288 {
1289   if (sRef_isObserver (fref) || sRef_isExposed (fref)
1290       || sRef_isPartial (fref))
1291     {
1292       ;
1293     }
1294   else
1295     {
1296       (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1297                                        loc, 0, DSC_LOCAL, FALSE);
1298     }
1299 }
1300
1301 void checkStructDestroyed (sRef fref, fileloc loc)
1302 {
1303   DPRINTF (("Check struct destroyed: %s", sRef_unparse (fref)));
1304
1305   if (sRef_isObserver (fref) || sRef_isExposed (fref)
1306       || sRef_isPartial (fref))
1307     {
1308       DPRINTF (("Its exposed!"));;
1309     }
1310   else
1311     {
1312       (void) checkCompletelyDestroyed (exprNode_undefined, fref, TRUE,
1313                                        loc, 0, DSC_STRUCT, FALSE);
1314     }
1315 }
1316
1317 static bool
1318   checkCompletelyDestroyed (exprNode fexp, sRef fref, bool topLevel,
1319                             fileloc loc, int depth,
1320                             dscCode desc, bool hideErrors)
1321 {
1322   ctype ct;
1323
1324   DPRINTF (("Check completely destroyed: %s", sRef_unparseFull (fref)));
1325
1326   if (depth > MAXDEPTH)
1327     {
1328       llquietbug (message ("checkCompletelyDestroyed: too deep: %s / %q", 
1329                            exprNode_unparse (fexp),
1330                            sRef_unparseFull (fref)));
1331       return TRUE;
1332     }
1333
1334   if (!sRef_isKnown (fref)) return TRUE;
1335
1336   /* evans 2001-03-24: added this.  Definitely null values are always destroyed. */
1337
1338   if (sRef_isDefinitelyNull (fref))
1339     {
1340       return TRUE;
1341     }
1342
1343   if (sRef_isDependent (fref) || sRef_isShared (fref) || sRef_isKept (fref))
1344     {
1345       return TRUE;
1346     }
1347
1348   {
1349     /*
1350     ** evans 2001-03-24: if there is a dependent reference to this storage,
1351     **    no need to destroy, but make it responsible.
1352     */
1353                                                          
1354     sRef depRef = dependentReference (fref);
1355
1356     DPRINTF (("Destroyed? %s / %s",
1357               sRef_unparseFull (fref),
1358               sRef_unparseFull (depRef)));
1359
1360     DPRINTF (("Aliases: %s", usymtab_unparseAliases ()));
1361
1362     if (sRef_isValid (depRef))
1363       {
1364         /*
1365         ** If the referenced storage was not dependent, we make
1366         ** the reference the owner since it must eventually be
1367         ** destroyed.
1368         */
1369
1370         if (!sRef_isDependent (depRef)) 
1371           {
1372             sRef_setOnly (depRef, loc); /* could be owned? */
1373           }
1374
1375         sRef_kill (fref, loc);
1376         return TRUE;
1377       }
1378   }
1379
1380   if (sRef_isPdefined (fref) && !context_getFlag (FLG_STRICTDESTROY))
1381     {
1382       DPRINTF (("Partial: %s", sRef_unparseFull (fref)));
1383       hideErrors = TRUE; /* Don't report any more errors, but still change ownership. */
1384     }
1385
1386   if (usymtab_isDefinitelyNull (fref)) 
1387     {
1388       DPRINTF (("Probably null!"));
1389       return TRUE;
1390     }
1391
1392   if (!context_getFlag (FLG_COMPDESTROY)) return TRUE;
1393   if (!context_getFlag (FLG_MUSTFREE)) return TRUE;
1394   
1395   ct = ctype_realType (sRef_getType (fref));
1396
1397   DPRINTF (("Here: %s", ctype_unparse (ct)));
1398
1399   if (!topLevel)
1400     {
1401       bool docheck = FALSE;
1402       bool reportederror;
1403
1404       if (sRef_isFresh (fref) || sRef_isOnly (fref))
1405         {
1406           docheck = TRUE;
1407           
1408           DPRINTF (("Here: %s", ctype_unparse (ct)));
1409           if (sRef_isDead (fref) 
1410               || sRef_isUnuseable (fref)
1411               || sRef_definitelyNull (fref)
1412               || sRef_isObserver (fref) 
1413               || sRef_isExposed (fref))
1414             {
1415               docheck = FALSE;
1416             }
1417         }
1418       
1419       if (docheck)
1420         {
1421           if (sRef_isPossiblyDead (fref) || sRef_isRelDef (fref))
1422             {
1423               if (exprNode_isDefined (fexp))
1424                 {
1425                   reportederror = 
1426                     !hideErrors 
1427                     && 
1428                     optgenerror2 
1429                     (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1430                      message ("Only storage %q (type %s) derived from %s "
1431                               "may not have been released: %s",
1432                               sRef_unparse (fref), 
1433                               ctype_unparse (sRef_getType (fref)),
1434                               dscCode_unparse (desc),
1435                               exprNode_unparse (fexp)),
1436                      loc);
1437                 }
1438               else
1439                 {
1440                   reportederror =
1441                     !hideErrors
1442                     &&
1443                     optgenerror2 
1444                     (FLG_COMPDESTROY, FLG_STRICTDESTROY,
1445                      message 
1446                      ("Only storage %q (type %s) derived from %s "
1447                       "may not have been released",
1448                       sRef_unparse (fref), 
1449                       ctype_unparse (sRef_getType (fref)),
1450                       dscCode_unparse (desc)),
1451                      loc);
1452                 }
1453               
1454               if (reportederror)
1455                 {
1456                   sRef_kill (fref, loc); /* prevent further errors */
1457                 }
1458             }
1459           else 
1460             {
1461               if (sRef_isStateUndefined (fref))
1462                 {
1463                   DPRINTF (("Here: %s", ctype_unparse (ct)));
1464                   return TRUE;
1465                 }
1466               else
1467                 {
1468                   if (exprNode_isDefined (fexp))
1469                     {
1470                       DPRINTF (("Here: %s", sRef_unparseFull (fref)));
1471
1472                       reportederror =
1473                         !hideErrors
1474                         &&
1475                         optgenerror 
1476                         (FLG_COMPDESTROY,
1477                          message ("Only storage %q (type %s) derived from %s "
1478                                   "is not released (memory leak): %s",
1479                                   sRef_unparse (fref),
1480                                   ctype_unparse (sRef_getType (fref)),  
1481                                   dscCode_unparse (desc),
1482                                   exprNode_unparse (fexp)),
1483                          loc);
1484                     }
1485                   else
1486                     {
1487                       reportederror = 
1488                         !hideErrors
1489                         &&
1490                         optgenerror 
1491                         (FLG_COMPDESTROY,
1492                          message ("Only storage %q (type %s) derived from %s "
1493                                   "is not released (memory leak)",
1494                                   sRef_unparse (fref),
1495                                   ctype_unparse (sRef_getType (fref)),
1496                                   dscCode_unparse (desc)),
1497                          loc);
1498                     }
1499
1500                   if (reportederror)
1501                     {
1502                       hideErrors = TRUE;
1503                       
1504                       /* sRef_kill (fref, loc); */ /* prevent further errors */
1505                       DPRINTF (("Killed: %s", sRef_unparseFull (fref)));
1506                     }
1507                 }
1508             }
1509
1510           DPRINTF (("Here: %s", ctype_unparse (ct)));
1511           return FALSE;
1512         }
1513       
1514       if (/*! evs-2002-03-24 sRef_isAnyDefined (fref) || */
1515           sRef_isDead (fref)
1516           || (sRef_isPdefined (fref) 
1517               && sRefSet_isEmpty (sRef_derivedFields (fref)))) 
1518         {
1519           DPRINTF (("Here: %s [%s / %s]", 
1520                     sRef_unparseFull (fref),
1521                     bool_unparse (sRef_isAnyDefined (fref)),
1522                     bool_unparse (sRef_isDead (fref))));
1523           return TRUE; 
1524         }
1525     }
1526
1527   DPRINTF (("Here..."));
1528
1529   if (ctype_isPointer (ct))
1530     {
1531       sRef fptr = sRef_constructDeadDeref (fref);
1532       bool res;
1533
1534       res = checkCompletelyDestroyed (fexp, fptr, FALSE, loc,
1535                                       depth + 1, desc, hideErrors);
1536       
1537       return res;
1538     }
1539   else if (ctype_isArray (ct))
1540     {
1541       if ((sRef_isStateUnknown (fref) || sRef_isAllocated (fref))
1542           && !sRef_hasDerived (fref))
1543         {
1544           /*
1545           ** Bogosity necessary to prevent infinite depth.
1546           */
1547
1548           return FALSE;
1549         }
1550       else
1551         {
1552           sRef farr = sRef_constructDeadDeref (fref);
1553           
1554           return (checkCompletelyDestroyed (fexp, farr, FALSE, loc, 
1555                                             depth + 1, desc, hideErrors));
1556         }
1557     }
1558   else if (ctype_isStruct (ct))
1559     {
1560       /*
1561       ** for structures, each field must be completely destroyed
1562       */
1563
1564       bool isOk = TRUE;
1565       uentryList fields = ctype_getFields (ct);
1566
1567       DPRINTF (("Struct fields: %s", uentryList_unparse (fields)));
1568
1569       if (depth >= MAXDEPTH)
1570         {
1571           llquietbug (message ("checkCompletelyDestroyed (fields): too deep: %s / %q", 
1572                                exprNode_unparse (fexp),
1573                                sRef_unparseFull (fref)));
1574                               
1575           return TRUE;
1576         }
1577       else
1578         {
1579           uentryList_elements (fields, ue)
1580             {
1581               sRef field = sRef_makeField (fref, uentry_rawName (ue));
1582               
1583               /*
1584               ** note order of && operands --- want to report multiple errors
1585               */
1586               
1587               DPRINTF (("Check field: %s", sRef_unparseFull (field)));
1588
1589               isOk = (checkCompletelyDestroyed (fexp, field, FALSE, loc,
1590                                                 depth + 1, desc, hideErrors)
1591                       && isOk);
1592             } end_uentryList_elements;
1593         }
1594
1595       return isOk;
1596     }
1597   else
1598     {
1599       return TRUE;
1600     }
1601 }
1602
1603 void
1604 checkReturnTransfer (exprNode fexp, uentry rval)
1605 {
1606   sRef uref = uentry_getSref (rval);
1607   sRef rref = sRef_makeNew (sRef_getType (uref), uref, cstring_undefined);
1608   uentry fcn = context_getHeader ();
1609   sRef fref = exprNode_getSref (fexp);
1610   stateClauseList clauses = uentry_getStateClauseList (fcn);
1611   
1612   DPRINTF (("Check return: %s as %s = %s",
1613             exprNode_unparse (fexp),
1614             sRef_unparseFull (uref),
1615             sRef_unparseFull (rref)));
1616
1617   /* evans 2001-07-18: removed: if (sRef_isStateSpecial (rref)) */
1618
1619   DPRINTF (("Check state clauses: %s",
1620             stateClauseList_unparse (clauses)));
1621   
1622   stateClauseList_postElements (clauses, cl)
1623     {
1624       if (stateClause_isGlobal (cl))
1625         {
1626           ; /*@i32@*/
1627         }
1628       else if (stateClause_setsMetaState (cl))
1629         {
1630           sRefSet refs = stateClause_getRefs (cl);
1631           qual ql = stateClause_getMetaQual (cl);
1632           annotationInfo ainfo = qual_getAnnotationInfo (ql);
1633           metaStateInfo minfo = annotationInfo_getState (ainfo);
1634           cstring key = metaStateInfo_getName (minfo);
1635           int mvalue = annotationInfo_getValue (ainfo);
1636           
1637           DPRINTF (("Return check: %s", stateClause_unparse (cl)));
1638           
1639           sRefSet_elements (refs, el)
1640             {
1641               sRef base = sRef_getRootBase (el);
1642               
1643               DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
1644               
1645               if (sRef_isResult (base))
1646                 {
1647                   sRef sr = sRef_fixBase (el, fref);
1648                   
1649                   if (!sRef_checkMetaStateValue (sr, key, mvalue))
1650                     {
1651                       if (optgenerror 
1652                           (FLG_STATETRANSFER,
1653                            message ("Result state %q does not satisfy ensures "
1654                                     "clause: %q (state is %q, should be %s): %s",
1655                                     sRef_unparse (sr),
1656                                     stateClause_unparse (cl),
1657                                     stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
1658                                                              minfo),
1659                                     metaStateInfo_unparseValue (minfo, mvalue),
1660                                     exprNode_unparse (fexp)),
1661                            exprNode_loc (fexp)))
1662                         {
1663                           sRef_showAliasInfo (sr); 
1664                           /*@i32@*/
1665                         }
1666                     }
1667                 }
1668               else 
1669                 {
1670                   /*
1671                   ** Non-results are checked in exit scope.
1672                   */
1673                 }
1674             } end_sRefSet_elements ;
1675         }
1676       else
1677         {
1678           sRefSet refs = stateClause_getRefs (cl);
1679           sRefTest tst = stateClause_getPostTestFunction (cl);
1680           sRefMod modf = stateClause_getReturnEffectFunction (cl);
1681           
1682           DPRINTF (("Clause: %s / %s",
1683                     stateClause_unparse (cl),
1684                     sRefSet_unparse (refs)));
1685           
1686           sRefSet_elements (refs, el)
1687             {
1688               sRef base = sRef_getRootBase (el);
1689               
1690               DPRINTF (("el: %s / %s", sRef_unparse (el),
1691                         sRef_unparse (base)));
1692               
1693               if (sRef_isResult (base))
1694                 {
1695                   sRef sr = sRef_fixBase (el, fref);
1696                   
1697                   if (tst != NULL && !(tst (sr)))
1698                     {
1699                       if (optgenerror 
1700                           (stateClause_postErrorCode (cl),
1701                            message ("%s storage %q corresponds to "
1702                                     "storage %q listed in %q clause: %s",
1703                                     stateClause_postErrorString (cl, sr),
1704                                     sRef_unparse (sr),
1705                                     sRef_unparse (el),
1706                                     stateClause_unparseKind (cl),
1707                                     exprNode_unparse (fexp)),
1708                            exprNode_loc (fexp)))
1709                         {
1710                           sRefShower ss = stateClause_getPostTestShower (cl);
1711                           
1712                           if (ss != NULL)
1713                             {
1714                               ss (sr);
1715                             }
1716                         }
1717                     }
1718                   
1719                   if (modf != NULL)
1720                     {
1721                       modf (sr, exprNode_loc (fexp));
1722                     }
1723                 }
1724               else
1725                 {
1726                   /* 
1727                   ** Non-results are checked in exit scope.
1728                   */
1729                 }
1730             } end_sRefSet_elements ;
1731         }
1732     } end_stateClauseList_postElements ;
1733   
1734   if (ctype_isRealSU (exprNode_getType (fexp)))
1735     {
1736       sRef ffref = exprNode_getSref (fexp);
1737           
1738       checkStructTransfer (exprNode_undefined, rref, 
1739                            fexp, ffref,
1740                            exprNode_loc (fexp),
1741                            TT_FCNRETURN);
1742     }
1743   else
1744     {
1745       (void) checkTransfer (fexp, exprNode_getSref (fexp),
1746                             exprNode_undefined, rref, 
1747                             exprNode_undefined,
1748                             exprNode_loc (fexp), TT_FCNRETURN);
1749     }
1750 }
1751
1752 static void
1753   checkPassstateClauseList (uentry ue, exprNode fexp, sRef fref, int argno)
1754 {
1755   stateClauseList clauses = uentry_getStateClauseList (ue);
1756
1757   DPRINTF (("Check pass special: %s / %s",
1758             exprNode_unparse (fexp), sRef_unparseFull (fref)));
1759   
1760   stateClauseList_preElements (clauses, cl)
1761     {
1762       if (stateClause_isGlobal (cl))
1763         {
1764           ;
1765         }
1766       else
1767         {
1768           sRefSet refs = stateClause_getRefs (cl);
1769           sRefTest tst = stateClause_getPreTestFunction (cl);
1770           sRefMod modf = stateClause_getEffectFunction (cl);
1771           
1772           sRefSet_elements (refs, el)
1773             {
1774               sRef base = sRef_getRootBase (el);
1775               
1776               if (sRef_isResult (base))
1777                 {
1778                   ; /* nothing to check before */
1779                 }
1780               else if (sRef_isParam (base))
1781                 {
1782                   if (sRef_getParam (base) == argno - 1)
1783                     {
1784                       sRef sb;
1785                       
1786                       DPRINTF (("Fix base: %s / %s",
1787                                 sRef_unparseFull (el),
1788                                 sRef_unparseFull (fref)));
1789                       
1790                       sb = sRef_fixBase (el, fref);
1791                       
1792                       if (tst != NULL && !(tst(sb)))
1793                         {
1794                           voptgenerror 
1795                             (stateClause_preErrorCode (cl),
1796                              message ("%s storage %qcorresponds to "
1797                                       "storage listed in %q clause of "
1798                                       "called function: %s",
1799                                       stateClause_preErrorString (cl, sb),
1800                                       sRef_unparseOpt (sb),
1801                                       stateClause_unparseKind (cl),
1802                                       exprNode_unparse (fexp)),
1803                              exprNode_loc (fexp));
1804                         }
1805                       
1806                       if (modf != NULL)
1807                         {
1808                           DPRINTF (("Fixing: %s", sRef_unparseFull (sb)));
1809                           modf (sb, exprNode_loc (fexp));
1810                           DPRINTF (("==> %s", sRef_unparseFull (sb)));
1811                         }
1812                     }
1813                 }
1814               else
1815                 {
1816                   BADBRANCH;
1817                 }
1818             } end_sRefSet_elements ;      
1819         }
1820     } end_stateClauseList_preElements ;
1821
1822     DPRINTF (("After: %s", sRef_unparseFull (fref)));
1823 }
1824
1825 /*
1826 ** should not modify arg
1827 */
1828
1829 void
1830 checkPassTransfer (exprNode fexp, uentry arg, bool isSpec,
1831                    /*@dependent@*/ exprNode fcn, int argno, int totargs)
1832 {
1833   sRef tref = uentry_getSref (arg);
1834   sRef fref = exprNode_getSref (fexp);
1835   bool isOut = FALSE;
1836   bool isPartial = FALSE;
1837   bool isImpOut = FALSE;
1838   ctype ct = uentry_getType (arg);
1839
1840   DPRINTF (("Check pass: %s -> %s",
1841             sRef_unparseFull (fref),
1842             sRef_unparseFull (tref)));
1843   
1844   atFunction = fcn;
1845   atArgNo = argno;
1846   atNumArgs = totargs;
1847
1848   if (ctype_isElips (ct))
1849     {
1850       ct = ctype_unknown;
1851     }
1852
1853   DPRINTF (("Out arg: %s", bool_unparse (uentry_isOut (arg))));
1854
1855   if (!ctype_isElips (ct) && 
1856       (ctype_isVoidPointer (ct) && uentry_isOut (arg) && sRef_isOnly (tref)))
1857     {
1858       if (ctype_isRealAP (ct))
1859         {
1860           if (sRef_aliasCheckSimplePred (sRef_isDead, fref))
1861             {
1862               if (optgenerror
1863                   (FLG_USERELEASED,
1864                    message ("Dead storage %qpassed as out parameter to %s: %s",
1865                             sRef_unparseOpt (fref),
1866                             exprNode_unparse (fcn),
1867                             exprNode_unparse (fexp)),
1868                    exprNode_loc (fexp)))
1869                 {
1870                   if (sRef_isDead (fref))
1871                     {
1872                       sRef_showStateInfo (fref);
1873                     }
1874                   else
1875                     {
1876                       DPRINTF (("Not really dead!"));
1877                       sRef_showStateInfo (fref);
1878                     }
1879                 }
1880               
1881               sRef_setAllocated (fref, exprNode_loc (fexp));
1882             }
1883           else if (context_getFlag (FLG_STRICTUSERELEASED)
1884                    && sRef_aliasCheckSimplePred (sRef_isPossiblyDead, fref))
1885             {
1886               if (optgenerror2 
1887                   (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1888                    message ("Possibly dead storage %qpassed as out parameter: %s",
1889                             sRef_unparseOpt (fref),
1890                             exprNode_unparse (fexp)),
1891                    exprNode_loc (fexp)))
1892                 {
1893                   if (sRef_isPossiblyDead (fref))
1894                     {
1895                       sRef_showStateInfo (fref);
1896                     }
1897                 }
1898               
1899               sRef_setAllocated (fref, exprNode_loc (fexp));
1900             }
1901           else if (sRef_aliasCheckSimplePred (sRef_isStateUndefined, fref) 
1902                    || sRef_aliasCheckSimplePred (sRef_isUnuseable, fref))
1903             {
1904               voptgenerror
1905                 (FLG_USEDEF,
1906                  message ("Unallocated storage %qpassed as out parameter: %s",
1907                           sRef_unparseOpt (fref),
1908                           exprNode_unparse (fexp)),
1909                  exprNode_loc (fexp));
1910
1911               sRef_setAllocated (fref, exprNode_loc (fexp));
1912             }
1913           else
1914             {
1915               ;
1916             }
1917         }
1918       
1919       (void) checkCompletelyDestroyed (fexp, fref, TRUE, exprNode_loc (fexp),
1920                                        0, DSC_PARAM, FALSE);
1921
1922       /* make it defined now, so checkTransfer is okay */
1923       sRef_setDefined (fref, exprNode_loc (fexp)); 
1924     }
1925   else if (uentry_isOut (arg))
1926     {
1927       DPRINTF (("Here we are!"));
1928
1929       if (ctype_isRealAP (ct)
1930           && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1931         {
1932           voptgenerror
1933             (FLG_USEDEF,
1934              message ("Unallocated 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           sRef_setAllocated (fref, exprNode_loc (fexp));
1940         }
1941       else if (sRef_isDead (fref))
1942         {
1943           if (optgenerror
1944               (FLG_USERELEASED,
1945                message ("Dead storage %qpassed as out parameter to %s: %s",
1946                         sRef_unparseOpt (fref),
1947                         exprNode_unparse (fcn),
1948                         exprNode_unparse (fexp)),
1949                exprNode_loc (fexp)))
1950             {
1951               sRef_showStateInfo (fref);
1952               sRef_setAllocated (fref, exprNode_loc (fexp));
1953             }
1954         }
1955       else if (sRef_isPossiblyDead (fref))
1956         {
1957           if (optgenerror2
1958               (FLG_USERELEASED, FLG_STRICTUSERELEASED,
1959                message ("Possibly dead storage %qpassed as out parameter to %s: %s",
1960                         sRef_unparseOpt (fref),
1961                         exprNode_unparse (fcn),
1962                         exprNode_unparse (fexp)),
1963                exprNode_loc (fexp)))
1964             {
1965               sRef_showStateInfo (fref);
1966               sRef_setAllocated (fref, exprNode_loc (fexp));
1967             }
1968         }
1969       else
1970         {
1971           ;
1972         }
1973       
1974       isOut = TRUE;
1975     }
1976   else if (uentry_isPartial (arg))
1977     {
1978       if (ctype_isRealAP (ct) 
1979           && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
1980         {
1981           voptgenerror 
1982             (FLG_USEDEF,
1983              message ("Unallocated storage %qpassed as partial parameter: %s",
1984                       sRef_unparseOpt (fref),
1985                       exprNode_unparse (fexp)),
1986              exprNode_loc (fexp));
1987           sRef_setAllocated (fref, exprNode_loc (fexp));
1988         }
1989       else if (sRef_isDead (fref))
1990         {
1991           if (optgenerror
1992               (FLG_USERELEASED,
1993                message ("Dead storage %qpassed as partial parameter to %s: %s",
1994                         sRef_unparseOpt (fref),
1995                         exprNode_unparse (fcn),
1996                         exprNode_unparse (fexp)),
1997                exprNode_loc (fexp)))
1998             {
1999               sRef_showStateInfo (fref);
2000               sRef_setAllocated (fref, exprNode_loc (fexp));
2001             }
2002         }
2003       else if (sRef_isPossiblyDead (fref))
2004         {
2005           if (optgenerror2
2006               (FLG_USERELEASED, FLG_STRICTUSERELEASED,
2007                message ("Possibly dead storage %qpassed as partial parameter to %s: %s",
2008                         sRef_unparseOpt (fref),
2009                         exprNode_unparse (fcn),
2010                         exprNode_unparse (fexp)),
2011                exprNode_loc (fexp)))
2012             {
2013               sRef_showStateInfo (fref);
2014               sRef_setAllocated (fref, exprNode_loc (fexp));
2015             }
2016         }
2017       else
2018         {
2019           ;
2020         }
2021
2022       isPartial = TRUE;
2023     }
2024   else if (uentry_isStateSpecial (arg))
2025     {
2026       uentry ue = exprNode_getUentry (fcn);
2027
2028       if (ctype_isRealAP (ct) 
2029           && (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref)))
2030         {
2031           voptgenerror 
2032             (FLG_USEDEF,
2033              message ("Unallocated storage %qpassed as special parameter: %s",
2034                       sRef_unparseOpt (fref),
2035                       exprNode_unparse (fexp)),
2036              exprNode_loc (fexp));
2037           sRef_setAllocated (fref, exprNode_loc (fexp));
2038         }
2039       else if (sRef_isDead (fref))
2040         {
2041           if (optgenerror
2042               (FLG_USERELEASED,
2043                message ("Dead storage %qpassed as special parameter to %s: %s",
2044                         sRef_unparseOpt (fref),
2045                         exprNode_unparse (fcn),
2046                         exprNode_unparse (fexp)),
2047                exprNode_loc (fexp)))
2048             {
2049               sRef_showStateInfo (fref);
2050               sRef_setAllocated (fref, exprNode_loc (fexp));
2051             }
2052         }
2053       else if (sRef_isPossiblyDead (fref))
2054         {
2055           if (optgenerror2
2056               (FLG_USERELEASED, FLG_STRICTUSERELEASED,
2057                message ("Possibly dead storage %qpassed as special parameter to %s: %s",
2058                         sRef_unparseOpt (fref),
2059                         exprNode_unparse (fcn),
2060                         exprNode_unparse (fexp)),
2061                exprNode_loc (fexp)))
2062             {
2063               sRef_showStateInfo (fref);
2064               sRef_setAllocated (fref, exprNode_loc (fexp));
2065             }
2066         }
2067       else
2068         {
2069           ;
2070         }
2071
2072       if (uentry_hasStateClauseList (ue))
2073         {
2074           checkPassstateClauseList (ue, fexp, fref, argno);
2075         }
2076       
2077       return; /* ??? */
2078     }
2079   else if (sRef_isStateDefined (tref))
2080     {
2081       exprNode_checkUseParam (fexp);
2082     }
2083   else
2084     {
2085       if (isSpec || (!context_getFlag (FLG_IMPOUTS)))
2086         {
2087           exprNode_checkUseParam (fexp);
2088         }
2089       else
2090         {
2091           if (!sRef_isMacroParamRef (fref) 
2092               && (ctype_isRealAP (ct)))
2093             {
2094               if (sRef_isAddress (fref))
2095                 {
2096                   if (sRef_isStateUndefined (fref) || sRef_isUnuseable (fref))
2097                     {
2098                       voptgenerror 
2099                         (FLG_USEDEF,
2100                          message 
2101                          ("Unallocated address %qpassed as implicit "
2102                           "out parameter: %s",
2103                           sRef_unparseOpt (fref),
2104                           exprNode_unparse (fexp)),
2105                          exprNode_loc (fexp));
2106                       sRef_setAllocated (fref, exprNode_loc (fexp));
2107                     }
2108                 }
2109               
2110               /* yes, I really mean this! */
2111               tref = sRef_copy (tref);
2112               sRef_setAllocated (tref, exprNode_loc (fexp)); 
2113
2114               isOut = TRUE;
2115               isImpOut = TRUE;
2116             }
2117           else 
2118             {
2119               exprNode_checkUseParam (fexp);
2120             }
2121         }
2122     }
2123
2124   if (sRef_isNew (fref))
2125     {
2126       alkind tkind = sRef_getAliasKind (tref);
2127
2128       if ((sRef_isFresh (fref) || sRef_isOnly (fref))
2129           && !alkind_isOnly (tkind) 
2130           && !alkind_isKeep (tkind) 
2131           && !alkind_isOwned (tkind)
2132           && !alkind_isError (tkind)
2133           && !uentry_isReturned (arg))
2134         
2135         {
2136           voptgenerror 
2137             (FLG_MUSTFREE,
2138              message ("New fresh storage %q(type %s) passed as %s (not released): %s",
2139                       sRef_unparseOpt (fref),
2140                       ctype_unparse (sRef_getType (fref)),
2141                       alkind_unparse (sRef_getAliasKind (tref)),
2142                       exprNode_unparse (fexp)),
2143              exprNode_loc (fexp));
2144           DPRINTF (("Fresh: %s", sRef_unparseFull (fref)));
2145         }
2146       else 
2147         {
2148           if (sRef_isNewRef (fref) && !sRef_isKillRef (tref))
2149             {
2150               alkind ak = sRef_getAliasKind (tref);
2151               
2152               if (!alkind_isError (ak))
2153                 {
2154                   voptgenerror 
2155                     (FLG_MUSTFREE,
2156                      message ("New reference %q(type %s) passed as %s (not released): %s",
2157                               sRef_unparseOpt (fref),
2158                               ctype_unparse (sRef_getType (fref)),
2159                               alkind_unparse (sRef_getAliasKind (tref)),
2160                               exprNode_unparse (fexp)),
2161                      exprNode_loc (fexp));
2162                 }
2163             }
2164         }
2165     }
2166   
2167   (void) checkTransfer (fexp, exprNode_getSref (fexp),
2168                         exprNode_undefined, tref,
2169                         fcn,
2170                         exprNode_loc (fexp), TT_FCNPASS);
2171
2172   setCodePoint ();
2173   fref = exprNode_getSref (fexp);
2174   
2175   if (isOut && !sRef_isDead (fref) && !sRef_isPossiblyDead (fref))
2176     {
2177       sRef base;
2178
2179       if (ctype_isRealAP (sRef_getType (fref)))
2180         {
2181           base = sRef_makePointer (fref); 
2182         }
2183       else
2184         {
2185           base = fref;
2186         }
2187
2188       if (isImpOut)
2189         {
2190           exprNode_checkMSet (fexp, base);
2191         }
2192       else
2193         {
2194           exprNode_checkSet (fexp, base);
2195         }
2196
2197       if (sRef_isValid (base))
2198         {
2199           setCodePoint ();
2200
2201           sRef_clearDerived (base);
2202           sRef_setDefined (base, exprNode_loc (fexp));
2203           usymtab_clearAlias (base);
2204           sRef_setNullUnknown (base, exprNode_loc (fexp));
2205         }
2206     }
2207
2208   if (isPartial)
2209     {
2210       if (sRef_isValid (fref))
2211         {
2212           sRef_setPartial (fref, exprNode_loc (fexp)); 
2213         }
2214     }
2215
2216   atFunction = exprNode_undefined;
2217   atArgNo = 0;
2218   atNumArgs = 0;
2219   
2220   /* need to fixup here: derived refs could be bogus */
2221   /* (better to change sRef to not add derivs for "protected" ref) */
2222
2223   uentry_fixupSref (arg);
2224
2225   setCodePoint ();
2226
2227   DPRINTF (("Check pass: ==> %s",
2228             sRef_unparseFull (fref)));
2229 }
2230
2231 void
2232 checkGlobReturn (uentry glob)
2233 {
2234   sRef_protectDerivs ();
2235   checkGlobTrans (glob, TT_GLOBRETURN);
2236   sRef_clearProtectDerivs ();
2237 }
2238
2239 void checkParamReturn (uentry actual)
2240 {
2241   checkLeaveTrans (actual, TT_PARAMRETURN);
2242 }
2243
2244 void checkLoseRef (uentry actual)
2245 {
2246   checkLeaveTrans (actual, TT_LEAVETRANS);
2247 }
2248
2249 static void
2250 checkLeaveTrans (uentry actual, transferKind transferType)
2251 {
2252   sRef aref = uentry_getSref (actual);
2253   sRef origref = uentry_getOrigSref (actual);
2254
2255   if (transferType == TT_PARAMRETURN 
2256       && (sRef_isKeep (origref) || sRef_isOnly (origref)
2257           || sRef_isOwned (origref)))
2258     {
2259       /* caller cannot use, nothing to check */
2260     }
2261   else
2262     {
2263       if (sRef_isNSLocalVar (origref))
2264         {
2265           ;
2266         }
2267       else
2268         {
2269           DPRINTF (("Leave trans: %s", uentry_unparseFull (actual)));
2270
2271           (void) checkCompletelyDefined (exprNode_undefined, aref, aref,
2272                                          exprNode_undefined, origref,
2273                                          TRUE, FALSE, FALSE,
2274                                          g_currentloc, transferType,
2275                                          0, TRUE);
2276         }
2277     }
2278 }
2279
2280 static void
2281 checkGlobTrans (uentry glob, transferKind type)
2282 {
2283   sRef eref = uentry_getOrigSref (glob);
2284   
2285   (void) checkCompletelyDefined (exprNode_undefined, uentry_getSref (glob), uentry_getSref (glob),
2286                                  exprNode_undefined, eref, 
2287                                  TRUE, FALSE, FALSE,
2288                                  g_currentloc, type, 0, TRUE);
2289 }
2290
2291 /*
2292 ** For lhs of assignment, alias kind is set from basic type.
2293 ** Yoikes!
2294 */
2295
2296 static void
2297 fixAssignLhs (sRef s)
2298 {
2299   sRef_resetStateComplete (s);
2300 }
2301
2302 static void checkStructTransfer (exprNode lhs, sRef slhs, exprNode rhs, sRef srhs,
2303                                  fileloc loc,
2304                                  transferKind tt)
2305 {
2306   ctype st = ctype_realType (sRef_getType (srhs));
2307   
2308   if (ctype_isSU (st) && ctype_isRealSU (sRef_getType (slhs))
2309       && ctype_match (sRef_getType (slhs), st))
2310     {
2311       if (tt == TT_DOASSIGN && sRef_isStateDefined (srhs))
2312         {
2313           sRef_setDefinedComplete (slhs, loc);
2314         }
2315           
2316       if (sRef_isDependent (slhs)
2317           || sRef_isObserver (slhs)
2318           || sRef_isExposed (slhs))
2319         {
2320           ;
2321         }
2322       else
2323         {
2324           if (sRef_isLocalVar (slhs)
2325               && sRef_isFileOrGlobalScope (sRef_getRootBase (srhs)))
2326             {
2327               sRef_setDependent (slhs, exprNode_loc (lhs));
2328             }
2329           else
2330             {
2331               if (ctype_isUnion (st))
2332                 {
2333                   sRef_setDefState (slhs, sRef_getDefState (srhs), 
2334                                     exprNode_loc (lhs));
2335
2336                   sRefSet_realElements (sRef_derivedFields (srhs), sr)
2337                     {
2338                       if (sRef_isField (sr))
2339                         {
2340                           cstring fieldname = sRef_getField (sr);
2341                           sRef lfld = sRef_makeField (slhs, fieldname);
2342
2343                           (void) checkTransfer (rhs, sr, lhs, lfld, 
2344                                                 exprNode_undefined,
2345                                                 exprNode_loc (lhs), tt);
2346                         }
2347                     } end_sRefSet_realElements ;
2348                 }
2349               else
2350                 {
2351                   uentryList fields = ctype_getFields (st);
2352                   
2353                   uentryList_elements (fields, field)
2354                     {
2355                       sRef rfld = sRef_makeField (srhs, uentry_rawName (field));
2356                       sRef lfld = sRef_makeField (slhs, uentry_rawName (field));
2357                       (void) checkTransfer (rhs, rfld, lhs, lfld, 
2358                                             exprNode_undefined,
2359                                             exprNode_loc (lhs), tt);
2360                     } end_uentryList_elements ;
2361                 }
2362
2363               if (sRef_isOnly (srhs))
2364                 {
2365                   sRef_setKeptComplete (srhs, loc);
2366                 }
2367             }
2368         }
2369     }
2370 }
2371
2372 void
2373 checkInitTransfer (exprNode lhs, exprNode rhs)
2374 {
2375   sRef slhs = exprNode_getSref (lhs);
2376   
2377   if (sRef_isFileOrGlobalScope (slhs) || (!sRef_isCvar (slhs)))
2378     {
2379       (void) checkTransfer (rhs, exprNode_getSref (rhs), 
2380                             lhs, slhs, 
2381                             exprNode_undefined,
2382                             exprNode_loc (rhs), TT_GLOBINIT);
2383     }
2384   else
2385     {
2386       checkAssignTransfer (lhs, rhs);
2387     }
2388 }
2389
2390 void
2391 checkAssignTransfer (exprNode lhs, exprNode rhs)
2392 {
2393   sRef slhs = exprNode_getSref (lhs);
2394   sRef srhs = exprNode_getSref (rhs);
2395   sRef base = sRef_getBaseSafe (slhs);
2396   nstate ns;
2397   
2398   DPRINTF (("Check assign: %s = %s", exprNode_unparse (lhs),
2399             exprNode_unparse (rhs)));
2400   DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2401   DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2402
2403   if (ctype_isRealSU (sRef_getType (srhs)))
2404     {
2405       checkStructTransfer (lhs, slhs, rhs, srhs, exprNode_loc (lhs), TT_FIELDASSIGN);
2406     }
2407   else
2408     {
2409       DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2410       DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2411       (void) checkTransfer (rhs, srhs, lhs, slhs, 
2412                             exprNode_undefined,
2413                             exprNode_loc (lhs), TT_DOASSIGN);
2414       DPRINTF (("lhs: %s", sRef_unparseFull (slhs)));
2415       DPRINTF (("rhs: %s", sRef_unparseFull (srhs)));
2416     }
2417
2418   if (sRef_isConst (srhs) && sRef_isLocalState (srhs))
2419     {
2420       /* constants can match anything (e.g., NULL) */
2421       sRef_setAliasKind (slhs, AK_ERROR, fileloc_undefined);
2422     }
2423
2424   if (sRef_isValid (base) && sRef_isStateDefined (base))
2425     {
2426       sRef_setPdefined (base, g_currentloc); 
2427     }
2428
2429   if (sRef_isPartial (srhs))
2430     {
2431       sRef_setPartial (slhs, exprNode_loc (rhs));
2432     }
2433
2434   ns = sRef_getNullState (srhs);
2435
2436   if (nstate_possiblyNull (ns))
2437     {
2438       if (usymtab_isGuarded (srhs))
2439         {
2440           ns = NS_NOTNULL;
2441         }
2442     }
2443
2444   sRef_setNullStateInnerComplete (slhs, ns, exprNode_loc (rhs));
2445
2446   if (sRef_isExposed (srhs) || sRef_isObserver (srhs))
2447     {
2448       sRef_setExKind (slhs, sRef_getExKind (srhs), exprNode_loc (rhs));
2449     }
2450   
2451   DPRINTF (("Done transfer: %s", sRef_unparseFull (slhs)));
2452 }
2453
2454 static void
2455 checkTransferNullAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2456                       sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2457                       fileloc loc, transferKind transferType)
2458 {
2459   alkind tkind = sRef_getAliasKind (tref);
2460   ctype ttyp = ctype_realType (sRef_getType (tref));
2461
2462   if (ctype_isUnknown (ttyp))
2463     {
2464       ttyp = exprNode_getType (texp);
2465       
2466       if (ctype_isUnknown (ttyp))
2467         {
2468           ttyp = exprNode_getType (fexp);
2469
2470           if (ctype_isUnknown (ttyp))
2471             {
2472               ttyp = sRef_getType (fref);
2473             }
2474         }
2475     }
2476
2477   if (ctype_isFunction (ttyp) && (transferType == TT_FCNRETURN))
2478     {
2479       ttyp = ctype_getReturnType (ttyp);
2480     }
2481
2482   /*
2483   ** check for null (don't need to check aliases??)
2484   */
2485
2486   if (sRef_possiblyNull (fref) 
2487       && !usymtab_isGuarded (fref) 
2488       && ctype_isRealAP (ttyp))
2489     {
2490       if (!alkind_isLocal (tkind) && !alkind_isFresh (tkind)
2491           && !sRef_perhapsNull (tref)
2492           && !(transferType == TT_DOASSIGN))
2493         {
2494           if (transferType == TT_GLOBINIT)
2495             {
2496               if (sRef_isNotNull (tref))
2497                 {
2498                   if (optgenerror
2499                       (FLG_SYNTAX, /*@i432 kuldge flag... */
2500                        message ("%s %q initialized to %s value: %q",
2501                                 sRef_getScopeName (tref),
2502                                 sRef_unparse (tref),
2503                                 sRef_nullMessage (fref),
2504                                 generateText (fexp, texp, tref, transferType)),
2505                        loc))
2506                     {
2507                       sRef_showNullInfo (fref);
2508                       sRef_setNullError (tref);
2509                     }
2510                 }
2511               else
2512                 {
2513                   if (optgenerror
2514                       (FLG_NULLASSIGN,
2515                        message ("%s %q initialized to %s value: %q",
2516                                 sRef_getScopeName (tref),
2517                                 sRef_unparse (tref),
2518                                 sRef_nullMessage (fref),
2519                                 generateText (fexp, texp, tref, transferType)),
2520                        loc))
2521                     {
2522                       sRef_showNullInfo (fref);
2523                       sRef_setNullError (tref);
2524                     }
2525                 }
2526             }
2527           else
2528             {
2529               if (optgenerror
2530                   ((transferType == TT_FCNPASS) ? FLG_NULLPASS : FLG_NULLRET,
2531                    message ("%q storage %q%s: %q",
2532                             cstring_capitalize (sRef_nullMessage (fref)),
2533                             sRef_unparseOpt (fref),
2534                             transferNullMessage (transferType), 
2535                             generateText (fexp, texp, tref, transferType)),
2536                    loc))
2537                 {
2538                   sRef_showNullInfo (fref);
2539                   sRef_setNullError (fref);
2540                 }
2541             }
2542         }
2543       else
2544         {
2545           ;
2546         }
2547     }  
2548 }
2549
2550
2551 static void
2552 checkTransferAssignAux (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
2553                         /*@exposed@*/ sRef tref, exprNode texp, bool tfix,
2554                         fileloc loc, transferKind transferType)
2555 {
2556   alkind tkind = sRef_getAliasKind (tref);
2557
2558   /*
2559   ** Assignment to same --- no errors, or state changes.
2560   ** This can happen when returned params are used.
2561   */
2562
2563   if (sRef_sameName (fref, tref))
2564     {
2565       sRef_copyState (tref, fref); 
2566       return;
2567     }
2568   
2569   if ((alkind_isOnly (tkind) || alkind_isFresh (tkind) 
2570        || alkind_isNewRef (tkind) || alkind_isOwned (tkind))
2571       && !(sRef_isDead (tref) 
2572            || sRef_isStateUndefined (tref) 
2573            || sRef_isUnuseable (tref) 
2574            || sRef_isPartial (tref)
2575            || sRef_definitelyNull (tref) 
2576            || sRef_isStackAllocated (tref) 
2577            || sRef_isAllocIndexRef (tref))
2578       && !(sRef_same (fref, tref)) /* okay to assign to self (returned params) */
2579       && !(usymtab_isDefinitelyNull (tref))) 
2580     {
2581       if (context_getFlag (FLG_MUSTFREE))
2582         {
2583           if (canLoseReference (tref, loc))
2584             {
2585               ; /* no error */
2586             }
2587           else
2588             {
2589               if (sRef_hasLastReference (tref))
2590                 {
2591                   if (optgenerror 
2592                       (FLG_MUSTFREE,
2593                        message ("Last reference %q to %s storage %q(type %s) not released "
2594                                 "before assignment: %q",
2595                                 sRef_unparse (tref),
2596                                 alkind_unparse (tkind),
2597                                 sRef_unparseOpt (sRef_getAliasInfoRef (tref)),
2598                                 ctype_unparse (sRef_getType (tref)),
2599                                 generateText (fexp, texp, tref, transferType)),
2600                        loc))
2601                     {
2602                       sRef_showRefLost (tref);
2603                     }
2604                 }
2605               else
2606                 {
2607                   if (context_inGlobalScope ())
2608                     {
2609                       /* no errors for static initializations */
2610                     }
2611                   else 
2612                     {
2613                       /*
2614                        ** don't report this error for a[i], since it could
2615                        ** be a new element.
2616                        */
2617                       
2618                       if (alkind_isNewRef (tkind))
2619                         {
2620                           if (optgenerror 
2621                               (FLG_MUSTFREE,
2622                                message 
2623                                ("%q %q(type %s) not released before assignment: %q",
2624                                 cstring_makeLiteral
2625                                 (alkind_isKillRef (sRef_getOrigAliasKind (tref))
2626                                  ? "Kill reference parameter" : "New reference"),
2627                                 sRef_unparseOpt (tref),
2628                                 ctype_unparse (sRef_getType (tref)),
2629                                 generateText (fexp, texp, tref, transferType)),
2630                                loc))
2631                             {
2632                               sRef_showAliasInfo (tref);
2633                               sRef_setAliasKind (tref, AK_ERROR, loc);
2634                             }
2635                         }
2636                       else if
2637                         (!(sRef_isUnknownArrayFetch (tref)
2638                            && !context_getFlag (FLG_STRICTDESTROY))
2639                          && !sRef_isUnionField (tref)
2640                          && !sRef_isRelDef (tref)
2641                          && optgenerror 
2642                          (FLG_MUSTFREE,
2643                           message 
2644                           ("%s storage %q(type %s) not released before assignment: %q",
2645                            alkind_capName (tkind),
2646                            sRef_unparseOpt (tref),
2647                            ctype_unparse (sRef_getType (tref)),
2648                            generateText (fexp, texp, tref, transferType)),
2649                           loc))
2650                           {
2651                             sRef_showAliasInfo (tref);
2652                           }
2653                       else
2654                         {
2655                           ;
2656                         }
2657                     }
2658                 }
2659             }
2660         }
2661     }
2662
2663   fixAssignLhs (tref);
2664
2665   if (sRef_isRefCounted (tref)) /* tkind might not be correct now */
2666     {
2667       if (sRef_isNewRef (fref))
2668         {
2669           sRef_setAliasKind (tref, AK_NEWREF, loc);
2670         }
2671       else if (sRef_isConst (fref))
2672         {
2673           /* for now, constants are not ref counted */
2674           sRef_setAliasKind (tref, AK_ERROR, loc);
2675         }
2676       else
2677         {
2678           ;
2679         }
2680
2681       if (!sRef_isNSLocalVar (tref) 
2682           && sRef_isRefCounted (fref)
2683           && sRef_isStateDefined (fref))
2684         {
2685           voptgenerror 
2686             (FLG_NEWREFTRANS,
2687              message ("New reference %qto reference counted storage: %q",
2688                       sRef_unparseOpt (tref),
2689                       generateText (fexp, texp, tref, transferType)),
2690              loc);
2691         }
2692     }
2693
2694   /*
2695   ** Not for structures and unions, since assignments copy.
2696   */
2697
2698   if (sRef_isStack (fref)
2699       && !ctype_isSU (ctype_realType (sRef_getType (fref))))
2700     {
2701       sRef_setAliasKindComplete (tref, AK_STACK, loc);
2702     }
2703
2704   if (sRef_isNSLocalVar (tref) 
2705       && !sRef_isOwned (tref) /*< should only apply to static >*/
2706       && ctype_isMutable (sRef_getType (tref)))
2707     {
2708       if (sRef_isOnly (fref) && sRef_isNew (fref)) 
2709         {
2710           if (!tfix) 
2711             {
2712               sRef_setFresh (tref, loc);
2713             }
2714         }
2715     }
2716 }
2717
2718 /*
2719 ** requires sRef_isOnly (fref)
2720 */
2721
2722 static void
2723 checkOnlyTransferAux (sRef fref, exprNode fexp, bool ffix,
2724                       sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2725                       fileloc loc, transferKind transferType)
2726 {     
2727   alkind tkind = sRef_getAliasKind (tref);
2728
2729   if (sRef_isExposed (tref) || sRef_isObserver (tref))
2730     {
2731       if (transferType == TT_FCNRETURN && sRef_isNew (fref)
2732           && !alkind_isError (tkind))
2733         {
2734           if (optgenerror 
2735               (FLG_ONLYTRANS,
2736                message ("Only storage %q%q (will not be released): %q",
2737                         sRef_unparseOpt (fref),
2738                         transferErrorMessage (transferType, tkind),
2739                         generateText (fexp, texp, tref, transferType)),
2740                loc))
2741             {
2742               sRef_showAliasInfo (fref);
2743             }
2744         }
2745       
2746       /* no errors for exposed transfers (is this good enough?) */
2747     }
2748   else if (alkind_isOnly (tkind) || alkind_isKeep (tkind) || alkind_isOwned (tkind))
2749     {
2750       ; /* okay */
2751     }
2752   else if ((transferType == TT_FCNPASS)
2753            && (alkind_isUnknown (tkind) 
2754                || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2755     {
2756       if (sRef_isFresh (fref) 
2757           && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2758         {
2759           if (!ffix) sRef_setAliasKind (fref, AK_UNKNOWN, loc); 
2760         }
2761     }
2762   else if (alkind_isLocal (tkind) 
2763            || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2764     {
2765       if ((transferType == TT_DOASSIGN)
2766           && sRef_isNew (fref) 
2767           && sRef_isOnly (fref))
2768         {
2769           bool error = FALSE;
2770
2771           if (alkind_isUnknown (tkind)
2772               && sRef_isFileOrGlobalScope (sRef_getRootBase (tref)))
2773             {
2774               if (optgenerror 
2775                   (FLG_ONLYUNQGLOBALTRANS,
2776                    message ("Only storage %q%q: %q",
2777                             sRef_unparseOpt (fref),
2778                             transferErrorMessage (transferType, tkind),
2779                             generateText (fexp, texp, tref, transferType)),
2780                    loc))
2781                 {
2782                   sRef_showAliasInfo (fref);
2783                   sRef_setAliasKind (tref, AK_ERROR, loc);
2784                   error = TRUE;
2785                 }
2786             }
2787
2788           if (!error && !ffix) 
2789             {
2790               sRef_setFresh (tref, loc);
2791             }
2792         }
2793       else
2794         {
2795           if (alkind_isLocal (tkind))
2796             {
2797               if (sRef_sameName (tref, fref))
2798                 {
2799                   ; /* don't set this --- corresponds to return transfer */
2800                 }
2801               else
2802                 {
2803                   /*
2804                   ** Don't set local to dependent.  Error will
2805                   ** be detected through aliasing.  Except for
2806                   ** arrays.
2807                   */
2808                   
2809                   if (!tfix && sRef_isThroughArrayFetch (fref)
2810                       && context_getFlag (FLG_DEPARRAYS))
2811                     {
2812                       sRef_setDependent (tref, loc);
2813                     }
2814                 }
2815             }
2816           else
2817             {
2818               if (optgenerror 
2819                   (FLG_ONLYTRANS,
2820                    message ("Only storage %q%q: %q",
2821                             sRef_unparseOpt (fref),
2822                             transferErrorMessage (transferType, tkind),
2823                             generateText (fexp, texp, tref, transferType)),
2824                    loc))
2825                 {
2826                   sRef_showAliasInfo (fref);
2827                 }
2828             }
2829         }
2830     }
2831   else
2832     {
2833       if (alkind_isError (tkind) 
2834           || (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT)))
2835         {
2836           flagcode_recordSuppressed (FLG_ONLYTRANS);
2837         }
2838       else
2839         {
2840           if ((alkind_isKept (tkind) || alkind_isStack (tkind) 
2841                || alkind_isDependent (tkind))
2842               && sRef_isNSLocalVar (tref))
2843             {
2844               ; /* okay */
2845             }
2846           else
2847             {
2848               if (optgenerror 
2849                   (FLG_ONLYTRANS,
2850                    message ("Only storage %q%q: %q",
2851                             sRef_unparseOpt (fref),
2852                             transferErrorMessage (transferType, tkind),
2853                             generateText (fexp, texp, tref, transferType)),
2854                    loc))
2855                 {
2856                   sRef_showAliasInfo (fref);
2857                   
2858                   if (transferType == TT_DOASSIGN)
2859                     {
2860                       /*
2861                       ** alias kind unknown to suppress future messages
2862                       */
2863                       
2864                       if (!ffix && sRef_isNSLocalVar (sRef_getRootBase (fref)))
2865                         {
2866                           sRef_clearAliasKind (fref);
2867                         }
2868                     }
2869                 }
2870             }
2871         }
2872     }
2873 }
2874
2875 /*
2876 ** ??? same as checkOnly ?
2877 */
2878
2879 static void
2880 checkOwnedTransferAux (sRef fref, exprNode fexp, bool ffix,
2881                        sRef tref, exprNode texp, bool tfix,
2882                        fileloc loc, transferKind transferType)
2883 {     
2884   alkind tkind = sRef_getAliasKind (tref);
2885
2886   if (sRef_isExposed (tref) || sRef_isObserver (tref))
2887     {
2888       if (transferType == TT_FCNRETURN && sRef_isNew (fref))
2889         {
2890           if (optgenerror 
2891               (FLG_OWNEDTRANS,
2892                message ("Owned storage %q%q (will not be released): %q",
2893                         sRef_unparseOpt (fref),
2894                         transferErrorMessage (transferType, tkind),
2895                         generateText (fexp, texp, tref, transferType)),
2896                loc))
2897             {
2898               sRef_showAliasInfo (fref);
2899             }
2900         }
2901     }
2902   else if (alkind_isOnly (tkind) || alkind_isKeep (tkind) 
2903            || alkind_isDependent (tkind)
2904            || alkind_isOwned (tkind))
2905     {
2906       /* okay */
2907     }
2908   else if (alkind_isLocal (tkind)
2909            || alkind_isFresh (tkind) || alkind_isUnknown (tkind))
2910     {
2911       if ((transferType == TT_DOASSIGN)
2912           && sRef_isNew (fref) && sRef_isOnly (fref))
2913         {
2914           if (!tfix) 
2915             { 
2916               sRef_setFresh (tref, loc); 
2917             }
2918         }
2919       else
2920         {
2921         }
2922     }
2923   else if ((transferType == TT_FCNPASS)
2924            && (alkind_isUnknown (tkind) 
2925                || alkind_isTemp (tkind) || alkind_isUnique (tkind)))
2926     {
2927       if (sRef_isFresh (fref) 
2928           && alkind_isUnknown (tkind) && !context_getFlag (FLG_PASSUNKNOWN))
2929         {
2930           if (!ffix) { sRef_clearAliasKind (fref); }
2931         }
2932     }
2933   else
2934     {
2935       if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2936         {
2937           flagcode_recordSuppressed (FLG_OWNEDTRANS);
2938         }
2939       else
2940         {
2941           if (alkind_isKept (tkind) && sRef_isNSLocalVar (tref))
2942             {
2943               ; /* okay */
2944             }
2945           else
2946             {
2947               voptgenerror
2948                 (FLG_OWNEDTRANS,
2949                  message ("Owned storage %q%q: %q",
2950                           sRef_unparseOpt (fref),
2951                           transferErrorMessage (transferType, tkind),
2952                           generateText (fexp, texp, tref, transferType)),
2953                  loc);
2954             }
2955         }
2956       
2957       if (transferType == TT_DOASSIGN)
2958         {
2959           /*
2960            ** alias kind unknown to suppress future messages
2961            */
2962           
2963           if (!ffix) { sRef_clearAliasKind (fref); }
2964         }
2965     }
2966 }
2967   
2968 static void
2969 checkFreshTransferAux (sRef fref, exprNode fexp, bool ffix,
2970                        sRef tref, exprNode texp, /*@unused@*/ bool tfix,
2971                        fileloc loc, transferKind transferType)
2972 {     
2973   alkind tkind = sRef_getAliasKind (tref);
2974
2975   /*
2976   ** error to return fresh as non-only
2977   */
2978
2979   if (transferType == TT_FCNRETURN
2980       && !(alkind_isOnly (tkind) || alkind_isNewRef (tkind)))
2981     {
2982       if (alkind_isUnknown (tkind) && !context_getFlag (FLG_MEMIMPLICIT))
2983         {
2984           flagcode_recordSuppressed (FLG_NEWREFTRANS);
2985         }
2986       else
2987         {
2988           if (alkind_isError (tkind))
2989             {
2990               if (!ffix) 
2991                 { 
2992                   sRef_killComplete (fref, loc); 
2993                 }
2994             }
2995           else if (alkind_isRefCounted (tkind))
2996             {
2997               if (optgenerror 
2998                   (FLG_NEWREFTRANS,
2999                    message
3000                    ("New reference returned without newref qualifier: %q",
3001                     generateText (fexp, texp, tref, transferType)),
3002                    loc))
3003                 {
3004                   sRef_showAliasInfo (fref);
3005                   sRef_killComplete (fref, loc);
3006                 }
3007               }
3008           else 
3009             {
3010               if (optgenerror 
3011                   (FLG_FRESHTRANS,
3012                    message ("Fresh storage %q (should be only): %q",
3013                             transferErrorMessage (transferType, tkind),
3014                             generateText (fexp, texp, tref, transferType)),
3015                    loc))
3016                 {
3017                   sRef_showAliasInfo (fref);
3018                   sRef_killComplete (fref, loc);
3019                 }
3020             }
3021         }
3022     }
3023   
3024   /*
3025   ** Okay to assign fresh to only, shared or unqualified.
3026   ** 
3027   ** should generate other errors? 
3028   */
3029
3030   if (alkind_isOnly (tkind))
3031     {
3032       if (transferType == TT_DOASSIGN && !sRef_isFileOrGlobalScope (tref))
3033         {
3034           if (!ffix) 
3035             { 
3036               if (!sRef_isNSLocalVar (tref))
3037                 {
3038                   sRef_setKeptComplete (fref, loc); 
3039                 }
3040             }
3041         }
3042       else
3043         {
3044           if (sRef_isConst (fref))
3045             {
3046               ;
3047             }
3048           else
3049             {
3050               if (!ffix) 
3051                 { 
3052                   sRef_killComplete (fref, loc); 
3053                 }
3054             }
3055         }
3056     }
3057   else if (alkind_isOwned (tkind))
3058     {
3059       if (!ffix) 
3060         { 
3061           sRef_setDependentComplete (fref, loc); 
3062         }
3063     }
3064   else if (alkind_isRefCounted (tkind)
3065            && (transferType == TT_FCNRETURN) && sRef_isFresh (fref))
3066     {
3067       if (!ffix) 
3068         { 
3069           sRef_killComplete (fref, loc); 
3070         }
3071     }
3072   else if (alkind_isKeep (tkind))
3073     {
3074       if (!ffix) 
3075         { 
3076           if (!sRef_isNSLocalVar (tref))
3077             {
3078               sRef_setKeptComplete (fref, loc); 
3079             }
3080         }
3081     }
3082   else if (alkind_isShared (tkind))
3083     {
3084       if (!ffix) { sRef_setShared (fref, loc); }
3085     }
3086   else if (alkind_isLocal (tkind) || alkind_isUnknown (tkind))
3087     {
3088       if (transferType == TT_DOASSIGN || transferType == TT_FCNRETURN)
3089         {
3090           /*
3091           ** local shares fresh.  Make it owned/dependent. 
3092           */
3093
3094           if (!tfix) 
3095             { 
3096               sRef_setOwned (tref, loc); 
3097             }
3098
3099           if (!ffix && !tfix) 
3100             { 
3101               sRef_setDependentComplete (fref, loc); 
3102             }
3103
3104           /* NO! sRef_clearAliasKind (fref); */
3105         }
3106       else 
3107         {
3108           if (context_getFlag (FLG_PASSUNKNOWN))
3109             {
3110               sRef_clearAliasKind (fref);
3111             }
3112         }
3113     }
3114   else
3115     {
3116       ;
3117     }
3118 }
3119
3120 static void
3121 checkTransferExposure (sRef fref, exprNode fexp, /*@unused@*/ bool ffix,
3122                        sRef tref, exprNode texp, bool tfix,
3123                        fileloc loc, 
3124                        transferKind transferType)
3125 {
3126   alkind fkind = sRef_getAliasKind (fref);
3127   alkind tkind = sRef_getAliasKind (tref);
3128   exkind tekind = sRef_getExKind (tref);
3129
3130   if (sRef_isObserver (fref) && ctype_isMutable (sRef_getType (fref)))
3131     {
3132       /*
3133       ** observer -> exposed or observer
3134       */
3135       
3136       /*
3137       ** observer -> temp is okay [NO!  really? only in function calls]
3138       */
3139
3140       if (sRef_isExposed (tref) || sRef_isObserver (tref)
3141           || alkind_isLocal (tkind))
3142         {
3143           /* okay */
3144           
3145           if ((transferType == TT_DOASSIGN) && alkind_isLocal (tkind))
3146             {
3147               if (!tfix) 
3148                 {
3149                   sRef_setAliasKindComplete (tref, fkind, loc); 
3150                 }
3151             }
3152         }
3153       else
3154         {
3155           if (transferType == TT_FCNRETURN 
3156               || transferType == TT_DOASSIGN
3157               || transferType == TT_FIELDASSIGN
3158               || transferType == TT_GLOBINIT)
3159             {
3160               bool hasError = FALSE;
3161               
3162               if (exprNode_isStringLiteral (fexp)
3163                   && transferType == TT_GLOBINIT)
3164                 {
3165                   hasError = optgenerror
3166                     (FLG_READONLYTRANS,
3167                      message ("Read-only string literal storage %q%q: %q",
3168                               sRef_unparseOpt (fref),
3169                               transferErrorExpMessage (transferType, tekind),
3170                               generateText (fexp, texp, tref, transferType)),
3171                      loc);
3172
3173                   sRef_setAliasKind (fref, AK_ERROR, fileloc_undefined);
3174                 }
3175               else 
3176                 {
3177                   if ((transferType == TT_DOASSIGN
3178                        || transferType == TT_FIELDASSIGN)
3179                       && (sRef_isNSLocalVar (tref)
3180                           || (exprNode_isStringLiteral (fexp)
3181                               && ctype_isRealArray (exprNode_getType (texp)))))
3182                     {
3183                       ; /* No error for local assignment or assignment
3184                            to static array (copies string). */
3185                     }
3186                   else
3187                     {
3188                       if (exprNode_isStringLiteral (fexp))
3189                         {
3190                           hasError = optgenerror 
3191                             (FLG_READONLYTRANS,
3192                              message
3193                              ("Read-only string literal storage %q%q: %q",
3194                               sRef_unparseOpt (fref),
3195                               transferErrorExpMessage (transferType, tekind),
3196                               generateText (fexp, texp, tref, transferType)),
3197                              loc);
3198                           
3199                         }
3200
3201                       if (!hasError)
3202                         {
3203                           hasError = optgenerror 
3204                             (FLG_OBSERVERTRANS,
3205                              message
3206                              ("Observer storage %q%q: %q",
3207                               sRef_unparseOpt (fref),
3208                               transferErrorExpMessage (transferType, tekind),
3209                               generateText (fexp, texp, tref, transferType)),
3210                              loc);
3211                         }
3212                     }
3213                 }
3214               
3215               if (hasError)
3216                 {
3217                   if (transferType != TT_GLOBINIT)
3218                     {
3219                       sRef_showExpInfo (fref);
3220                       sRef_setAliasKind (tref, AK_ERROR, loc);
3221                     }
3222                 }
3223               else 
3224                 {
3225                   if (transferType == TT_DOASSIGN && !tfix)
3226                     {
3227                       DPRINTF (("Setting unknown!"));
3228                       /* sRef_setAliasKind (tref, AK_ERROR, loc); */
3229                     }
3230                 }
3231             }
3232           else /* TT_FCNPASS */
3233             {
3234               llassert (transferType == TT_FCNPASS);
3235
3236               if (alkind_isTemp (tkind) 
3237                   || alkind_isDependent (tkind)
3238                   || alkind_isRefCounted (tkind))
3239                 {
3240                   ; /* okay */
3241                 }
3242               else 
3243                 {
3244                   if (!alkind_isError (tkind))
3245                     {
3246                       if (optgenerror 
3247                           (FLG_OBSERVERTRANS,
3248                            message ("Observer storage %q%q: %q",
3249                                     sRef_unparseOpt (fref),
3250                                     transferErrorMessage (transferType, tkind),
3251                                     generateText (fexp, texp, tref, transferType)),
3252                            loc))
3253                         {
3254                           sRef_showExpInfo (fref);
3255                           sRef_clearAliasState (fref, loc); 
3256                         }
3257                     }
3258                 }
3259             }
3260         }
3261     }
3262   else if (sRef_isExposed (fref) && ctype_isMutable (sRef_getType (fref)))
3263     {
3264       if (transferType == TT_FCNRETURN)
3265         {
3266           if (!(sRef_isExposed (tref) || sRef_isObserver (tref)
3267                 || sRef_isParam (fref)))
3268             {
3269               if (optgenerror
3270                   (FLG_EXPOSETRANS,
3271                    message ("Exposed storage %q%q: %q",
3272                             sRef_unparseOpt (fref),
3273                             transferErrorExpMessage (transferType, tekind),
3274                             generateText (fexp, texp, tref, transferType)),
3275                    loc))
3276                 {
3277                   sRef_showExpInfo (fref);
3278                 }
3279             }
3280         }
3281       else if (transferType == TT_FCNPASS)
3282         {
3283           if (!(sRef_isExposed (tref) 
3284                 || sRef_isObserver (tref)
3285                 || (alkind_isUnknown (tkind) 
3286                     || alkind_isDependent (tkind)
3287                     || alkind_isTemp (tkind)
3288                     || alkind_isKillRef (tkind)
3289                     || alkind_isRefCounted (tkind))))
3290             {
3291               if (alkind_isUnique (tkind) || alkind_isError (tkind))
3292                 {
3293                 }
3294               else 
3295                 {
3296                   if (optgenerror 
3297                       (FLG_EXPOSETRANS,
3298                        message ("Exposed storage %q%q: %q",
3299                                 sRef_unparseOpt (fref),
3300                                 transferErrorMessage (transferType, tkind),
3301                                 generateText (fexp, texp, tref, transferType)),
3302                        loc))
3303                     {
3304                       sRef_showExpInfo (fref);
3305                       sRef_clearAliasState (fref, loc); 
3306                     }
3307                 }
3308
3309             }
3310           else
3311             {
3312               ;
3313             }
3314         }
3315       else if (transferType == TT_DOASSIGN
3316                /* evans 2001-10-05: added TT_FIELDASSIGN: */
3317                || transferType == TT_FIELDASSIGN)
3318         {
3319           if (!(sRef_isExposed (tref) 
3320                 || !sRef_isCvar (tref)
3321                 || (alkind_isUnknown (tkind)
3322                     || alkind_isDependent (tkind)
3323                     || alkind_isRefCounted (tkind) 
3324                     || alkind_isNewRef (tkind)
3325                     || alkind_isFresh (tkind)
3326                     || alkind_isLocal (tkind))))
3327             {
3328               if (optgenerror 
3329                   (FLG_EXPOSETRANS,
3330                    message ("Exposed storage %q%q: %q",
3331                             sRef_unparseOpt (fref),
3332                             transferErrorExpMessage (transferType, tekind),
3333                             generateText (fexp, texp, tref, transferType)),
3334                    loc))
3335                 {
3336                   sRef_showExpInfo (fref);
3337                 }
3338             }
3339           if (!tfix) { sRef_setExposed (tref, loc); }
3340         }
3341       else
3342         {
3343           llassert (transferType == TT_GLOBPASS
3344                     || transferType == TT_GLOBRETURN
3345                     || transferType == TT_PARAMRETURN
3346                     || transferType == TT_LEAVETRANS
3347                     || transferType == TT_GLOBINIT);
3348         }
3349     }
3350   else
3351     {
3352       ;
3353     }
3354 }
3355
3356 /*
3357 ** returns TRUE if there is no error reported
3358 **
3359 ** if fixt, don't change tref (except if error reported.)
3360 ** if fixf, don't change fref (except if error reported.)
3361 */
3362
3363 static void
3364 checkTransferAux (exprNode fexp, /*@exposed@*/ sRef fref, bool ffix,
3365                   exprNode texp, /*@exposed@*/ sRef tref, bool tfix,
3366                   fileloc loc, transferKind transferType)
3367 {
3368   alkind fkind;
3369   alkind tkind;
3370   bool isassign = (transferType == TT_DOASSIGN);
3371   bool isfieldassign = (transferType == TT_FIELDASSIGN);
3372   bool iseitherassign = isassign || (transferType == TT_FIELDASSIGN);
3373   bool isfcnpass = (transferType == TT_FCNPASS);
3374   bool isfcnreturn = (transferType == TT_FCNRETURN);
3375
3376   setCodePoint ();
3377
3378   if (!ffix && !tfix)
3379     {
3380       setCodePoint ();
3381       checkTransferNullAux (fref, fexp, ffix, tref, texp, tfix, 
3382                             loc, transferType);
3383     }
3384
3385   if (isassign)
3386     {
3387       setCodePoint ();
3388       checkTransferAssignAux (fref, fexp, ffix, tref, texp, tfix,
3389                               loc, transferType);
3390     }
3391
3392   /*
3393   ** Check for definition 
3394   */
3395
3396   /*
3397   ** errors passing out params already detected in checkAnyCall
3398   */
3399
3400   if (!ffix && !tfix)
3401     {
3402       bool defok = TRUE;
3403
3404       if (!iseitherassign 
3405           || (!sRef_isNSLocalVar (tref) 
3406               && (sRef_isAnyDefined (tref) || !sRef_stateKnown (tref))))
3407         {
3408           setCodePoint ();
3409
3410           if (!ynm_toBoolRelaxed 
3411               (checkCompletelyDefined (fexp, fref, fref,
3412                                        texp, tref,
3413                                        TRUE, FALSE, FALSE, 
3414                                        loc, transferType, 0, TRUE)))
3415             {
3416               defok = FALSE;
3417             }
3418         }
3419
3420       setCodePoint ();
3421       
3422       if (defok && iseitherassign)
3423         {
3424           sRef_setDefState (tref, sRef_getDefState (fref), loc);
3425         }
3426     }
3427
3428   /*
3429   ** check exposure
3430   */
3431
3432   setCodePoint ();
3433   checkTransferExposure (fref, fexp, ffix, tref, texp, tfix, 
3434                          loc, transferType);
3435
3436   fkind = sRef_getAliasKind (fref);
3437   tkind = sRef_getAliasKind (tref);
3438
3439   /*
3440   ** check aliasing
3441   */
3442
3443   if (alkind_isOnly (fkind))
3444     {
3445       setCodePoint ();
3446       checkOnlyTransferAux (fref, fexp, ffix,
3447                             tref, texp, tfix, 
3448                             loc, transferType);
3449     }
3450   else if (alkind_isFresh (fkind))
3451     {
3452       setCodePoint ();
3453       checkFreshTransferAux (fref, fexp, ffix,
3454                              tref, texp, tfix,
3455                              loc, transferType);
3456     }
3457   else if (alkind_isOwned (fkind))
3458     {
3459       setCodePoint ();
3460       checkOwnedTransferAux (fref, fexp, ffix,
3461                              tref, texp, tfix,
3462                              loc, transferType);
3463     }
3464   else if (alkind_isDependent (fkind))
3465     {
3466       setCodePoint ();
3467       if (isfcnreturn && 
3468           (sRef_isExposed (tref) || sRef_isObserver (tref)))
3469         {
3470           ; /* okay */
3471         }
3472       else if ((alkind_isOnly (tkind) || alkind_isKeep (tkind)
3473                 || alkind_isOwned (tkind))
3474                || (!isfcnpass && alkind_isTemp (tkind)))
3475         {
3476           bool error = TRUE;
3477
3478           if (sRef_isLocalVar (fref))
3479             {
3480               sRef depRef = dependentReference (fref);
3481
3482               if (sRef_isValid (depRef) && sRef_isLocalVar (depRef))
3483                 {
3484                   error = FALSE;
3485                   sRef_kill (depRef, loc);
3486                   sRef_kill (fref, loc);
3487                 }
3488
3489             }
3490
3491           if (isfieldassign)
3492             {
3493               error = FALSE;
3494             }
3495
3496           if (canLoseLocalReference (fref, loc))
3497             {
3498               ;
3499             }
3500           else
3501             {
3502               if (error &&
3503                   (optgenerror 
3504                    (FLG_DEPENDENTTRANS,
3505                     message ("%s storage %q%q: %q",
3506                              alkind_capName (fkind),
3507                              sRef_unparseOpt (fref),
3508                              transferErrorMessage (transferType, tkind),
3509                              generateText (fexp, texp, tref, transferType)),
3510                     loc)))
3511                 {
3512                   DPRINTF (("Here: %s / %s", 
3513                             sRef_unparseFull (fref),
3514                             sRef_unparseFull (tref)));
3515
3516                   sRef_showAliasInfo (fref);
3517                 }
3518             }
3519         }
3520       else 
3521         {
3522           if (isassign && (alkind_isFresh (tkind) || alkind_isLocal (tkind)))
3523             {
3524               if (!tfix && !ffix)
3525                 {
3526                   sRef_setDependent (tref, loc);
3527                 }
3528             }
3529         }
3530     }
3531   else if (alkind_isShared (fkind))
3532     {
3533       setCodePoint ();
3534       /*
3535       ** xxx <- shared
3536       */
3537
3538       if (alkind_isOnly (tkind) 
3539           || (!isfcnpass 
3540               && (!(sRef_isObserver (tref) || sRef_isExposed (tref)) 
3541                   && alkind_isTemp (tkind))))
3542         {
3543           if (optgenerror
3544               (FLG_SHAREDTRANS,
3545                message ("%s storage %q%q: %q",
3546                         alkind_capName (fkind),
3547                         sRef_unparseOpt (fref),
3548                         transferErrorMessage (transferType, tkind),
3549                         generateText (fexp, texp, tref, transferType)),
3550                loc))
3551             {
3552               sRef_showAliasInfo (fref);
3553             }
3554         }
3555       else 
3556         {
3557           if (alkind_isFresh (tkind) || alkind_isLocal (tkind))
3558             {
3559               sRef_setShared (tref, loc);
3560             }
3561         }
3562     }
3563   else if (alkind_isKeep (fkind))
3564     {
3565       setCodePoint ();
3566
3567       if (alkind_isKeep (tkind) 
3568           || alkind_isLocal (tkind)
3569           || (isfcnreturn && sRef_isExposed (tref))
3570           || (iseitherassign 
3571               && (alkind_isOnly (tkind) || alkind_isOwned (tkind))))
3572         {
3573           sRef_setKept (fref, loc);
3574         }
3575       else if (isfcnpass 
3576                && (alkind_isTemp (tkind) || alkind_isOwned (tkind)))
3577         {
3578           ;
3579         }
3580       else 
3581         {
3582           if (!alkind_isError (tkind))
3583             {
3584               if (optgenerror
3585                   (FLG_KEEPTRANS,
3586                    message ("%s storage %q: %q",
3587                             alkind_capName (fkind),
3588                             transferErrorMessage (transferType, tkind),
3589                             generateText (fexp, texp, tref, transferType)),
3590                    loc))
3591                 {
3592                   sRef_showAliasInfo (fref);
3593                 }
3594             }
3595         }
3596     }
3597   else if (alkind_isTemp (fkind) || alkind_isKept (fkind))
3598     {
3599       /*
3600       ** xxx <- temp
3601       */
3602       
3603       if (alkind_isOnly (tkind)
3604           || alkind_isShared (tkind) 
3605           || (alkind_isTemp (fkind)
3606               && !isfcnreturn && alkind_isDependent (tkind))
3607           || alkind_isOwned (tkind)
3608           || alkind_isKeep (tkind))
3609         {
3610           if (!exprNode_isNullValue (fexp)
3611               && (ctype_isMutable (exprNode_getType (fexp))
3612                   || (ctype_isArray (exprNode_getType (fexp))
3613                       && sRef_isParam (fref)))
3614               && (!iseitherassign || sRef_isReference (tref)))
3615             {
3616               if (sRef_isThroughArrayFetch (fref))
3617                 {
3618                   if (optgenerror2
3619                       (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3620                        FLG_STRICTUSERELEASED,
3621                        message ("%s storage %q%q: %q",
3622                                 alkind_capName (fkind),
3623                                 sRef_unparseOpt (fref),
3624                                 transferErrorMessage (transferType, tkind),
3625                                 generateText (fexp, texp, tref, transferType)),
3626                        loc))
3627                     {
3628                       sRef_showAliasInfo (fref);
3629                     }
3630                 }
3631               else
3632                 {
3633                   if (optgenerror
3634                       (alkind_isTemp (fkind) ? FLG_TEMPTRANS : FLG_KEPTTRANS,
3635                        message ("%s storage %q%q: %q",
3636                                 alkind_capName (fkind),
3637                                 sRef_unparseOpt (fref),
3638                                 transferErrorMessage (transferType, tkind),
3639                                 generateText (fexp, texp, tref, transferType)),
3640                        loc))
3641                     {
3642                       sRef_showAliasInfo (fref);
3643                     }
3644                 }
3645             }
3646         }
3647     }
3648   else if (alkind_isRefCounted (fkind) || alkind_isKillRef (fkind))
3649     {
3650       if (alkind_isNewRef (tkind))
3651         {
3652           /*
3653           ** check that the refs field has been modified
3654           */
3655
3656           if (!sRef_isConst (fref))
3657             {
3658               voptgenerror 
3659                 (FLG_REFCOUNTTRANS,
3660                  message ("Reference counted storage returned without modifying "
3661                           "reference count: %s",
3662                           exprNode_unparse (fexp)),
3663                  loc);
3664             }
3665         }
3666       else if (iseitherassign)
3667         {
3668           if (alkind_isRefCounted (fkind))
3669             {
3670               if (!sRef_isLocalVar (tref))
3671                 {
3672                   vgenhinterror 
3673                     (FLG_REFCOUNTTRANS,
3674                      message 
3675                      ("Assignment to non-local from reference counted storage: %s",
3676                       exprNode_unparse (fexp)),
3677                      cstring_makeLiteral 
3678                      ("Reference counted storage should call a function returning "
3679                       "a newref instead of direct assignments."),
3680                      loc);
3681                 }
3682               else
3683                 {
3684                   ;
3685                 }
3686             }
3687         }
3688       else /* fcnpass */
3689         {
3690           if (alkind_isRefCounted (tkind) || alkind_isTemp (tkind))
3691             {
3692               /* okay --- no change in state */
3693             }
3694           else if (alkind_isKillRef (tkind))
3695             {
3696               if (!ffix && !tfix && !(transferType == TT_FCNRETURN))
3697                 { 
3698                   sRef_killComplete (fref, loc); 
3699                 }
3700             }
3701           else 
3702             {
3703               if (!alkind_isError (tkind))
3704                 {
3705                   voptgenerror
3706                     (FLG_REFCOUNTTRANS,
3707                      message ("Reference counted storage %q: %q",
3708                               transferErrorMessage (transferType, tkind),
3709                               generateText (fexp, texp, tref, transferType)),
3710                      loc);
3711                 }
3712             }
3713         }
3714     }
3715   else
3716     {
3717       ;
3718     }
3719
3720   setCodePoint ();
3721   
3722   if (alkind_isOnly (tkind) || alkind_isKeep (tkind))
3723     {
3724       if (sRef_isAddress (fref))
3725         {
3726           voptgenerror
3727             (FLG_IMMEDIATETRANS,
3728              message ("Immediate address %q %q: %q", 
3729                       sRef_unparse (fref),
3730                       transferErrorMessage (transferType, tkind),
3731                       generateText (fexp, texp, tref, transferType)),
3732              loc);
3733           
3734           sRef_setAliasKind (fref, AK_ERROR, loc);
3735         }
3736       else 
3737         {
3738           if ((alkind_isUnknown (fkind) || alkind_isStatic (fkind))
3739               && !sRef_isDefinitelyNull (fref)
3740               && (!ffix && !tfix)
3741               && (!exprNode_isNullValue (fexp)))
3742             {
3743               flagcode errkind = alkind_isStatic (fkind) 
3744                 ? FLG_STATICTRANS : FLG_UNKNOWNTRANS;
3745
3746               if (transferType == TT_GLOBINIT)
3747                 {
3748                   if (errkind == FLG_STATICTRANS)
3749                     {
3750                       errkind = FLG_STATICINITTRANS;
3751                     }
3752                   else
3753                     {
3754                       errkind = FLG_UNKNOWNINITTRANS;
3755                     }
3756                 }
3757
3758               if (optgenerror 
3759                   (errkind,
3760                    message ("%s storage %s %q: %q",
3761                             alkind_capName (fkind),
3762                             exprNode_unparse (fexp),
3763                             transferErrorMessage (transferType, tkind),
3764                             generateText (fexp, texp, tref, transferType)),
3765                    loc))
3766                 {
3767                   sRef_showAliasInfo (fref);
3768                 }
3769             }
3770         }
3771       
3772       /* don't kill shared to suppress future messages */
3773       if (!alkind_isShared (fkind))
3774         {
3775           if (isassign)
3776             {
3777               if (!ffix) 
3778                 {
3779                   /*< yuk! should do this in aliasaux >*/
3780                    
3781                   if (!sRef_isNSLocalVar (tref) && !sRef_sameName (fref, tref))
3782                     {
3783                       if (!tfix)
3784                         {
3785                           sRef_setKeptComplete (fref, loc);
3786                         }
3787                       else
3788                         {
3789                           sRef_setKept (fref, loc);
3790                         }
3791                     }
3792                 }
3793             }
3794           else
3795             {
3796               if (!ffix) 
3797                 {
3798                   if (!tfix)
3799                     {
3800                       if (alkind_isKeep (tkind))
3801                         {
3802                           sRef_setKeptComplete (fref, loc);
3803                         }
3804                       else
3805                         {
3806                           sRef_killComplete (fref, loc); 
3807                         }
3808                     }
3809                   else
3810                     {
3811                       if (alkind_isKeep (tkind))
3812                         {
3813                           sRef_setKept (fref, loc);
3814                         }
3815                       else
3816                         {
3817                           sRef_kill (fref, loc);
3818                         }
3819                     }
3820                 }
3821             }
3822         }
3823     }
3824   else if (alkind_isOwned (tkind))
3825     {
3826       /* don't kill shared to suppress future messages */
3827       if (!alkind_isShared (fkind)) 
3828         {
3829           if (!isassign 
3830               || !sRef_sameName (fref, tref)) /* result of return parameter */
3831             {
3832               if (!ffix)
3833                 {
3834                   if (!tfix)
3835                     {
3836                       sRef_setDependentComplete (fref, loc);
3837                     }
3838                   else
3839                     {
3840                       sRef_setDependent (fref, loc);
3841                     }
3842                 }
3843             }
3844         }
3845     }
3846   else if (alkind_isShared (tkind))
3847     {
3848       if (alkind_isFresh (fkind) || alkind_isLocal (fkind))
3849         {
3850           if (!ffix) 
3851             {
3852               sRef_setShared (fref, loc);
3853             }
3854         }
3855     }
3856   else if (alkind_isUnknown (tkind) && context_getFlag (FLG_MEMIMPLICIT))
3857     {
3858       if (alkind_isDependent (fkind))
3859         {
3860           if (!exprNode_isNullValue (fexp)
3861               && ctype_isMutable (exprNode_getType (fexp))
3862               && (!iseitherassign || sRef_isReference (tref)))
3863             {
3864               if (canLoseReference (fref, loc))
3865                 {
3866                   ;
3867                 }
3868               else
3869                 {
3870                   if (optgenerror
3871                       (FLG_DEPENDENTTRANS,
3872                        message ("%s storage %q%q: %q",
3873                                 alkind_capName (fkind),
3874                                 sRef_unparseOpt (fref),
3875                                 transferErrorMessage (transferType, tkind),
3876                                 generateText (fexp, texp, tref, transferType)),
3877                        loc))
3878                     {
3879                       DPRINTF (("Here: %s / %s", sRef_unparseFull (fref),
3880                                 sRef_unparseFull (tref)));
3881                       sRef_showAliasInfo (fref);
3882                     }
3883                 }
3884             }
3885         }
3886     }
3887   else if (alkind_isNewRef (tkind))
3888     {
3889       if (!ffix && !tfix)
3890         { 
3891           sRef_killComplete (fref, loc);  
3892         }
3893     }
3894   else if (alkind_isKillRef (tkind))
3895     {
3896       if (transferType == TT_FCNRETURN)
3897         {
3898           if (sRef_isNewRef (fref))
3899             {
3900               if (optgenerror
3901                   (FLG_REFCOUNTTRANS,
3902                    message ("New reference returned as temp reference: %q",
3903                             generateText (fexp, texp, tref, transferType)),
3904                    loc))
3905                 {
3906                   sRef_showAliasInfo (fref);
3907                 }
3908               }
3909         }
3910       else
3911         {
3912           if (sRef_isNewRef (fref))
3913             {
3914               sRef_killComplete (fref, loc);
3915             }
3916           else 
3917             {
3918               if (sRef_isRefCounted (fref) 
3919                   && sRef_isCvar (fref)
3920                   && !sRef_isLocalVar (fref))
3921                 {
3922                   if (optgenerror
3923                       (FLG_REFCOUNTTRANS,
3924                        message 
3925                        ("External reference counted storage released: %q",
3926                         generateText (fexp, texp, tref, transferType)),
3927                        loc))
3928                     {
3929                       sRef_showAliasInfo (fref);
3930                     }
3931                 }
3932             }
3933         }
3934           
3935     }
3936   else
3937     {
3938       ;
3939     }
3940
3941   setCodePoint ();
3942 }
3943
3944 static void
3945 checkMetaStateConsistent (/*@exposed@*/ sRef fref, sRef tref, 
3946                           fileloc loc, /*@unused@*/ transferKind transferType)
3947 {
3948   /*
3949   ** Checks if it is consistent to leave storage marked as tref in state of fref.
3950   */
3951
3952   valueTable fvalues = sRef_getValueTable (fref);
3953   valueTable tvalues = sRef_getValueTable (tref);
3954   
3955   DPRINTF (("Metastate consistent: %s => %s",
3956             sRef_unparseFull (fref),
3957             sRef_unparseFull (tref)));
3958   
3959   if (valueTable_isUndefined (tvalues) || valueTable_isUndefined (fvalues)) {
3960     /* Cannot check without value tables.  An error was already detected. */
3961     DPRINTF (("No value table: %s / %s",
3962               bool_unparse (valueTable_isUndefined (tvalues)),
3963               bool_unparse (valueTable_isUndefined (fvalues))));
3964     return;
3965   }
3966
3967   valueTable_elements (fvalues, fkey, fval) {
3968     stateValue tval;
3969     metaStateInfo minfo;
3970
3971     DPRINTF (("Transfer: %s", fkey));
3972     tval = valueTable_lookup (tvalues, fkey);
3973     minfo = context_lookupMetaStateInfo (fkey);
3974
3975     if (!stateValue_isDefined (tval)) 
3976       {
3977         if (ctype_isUnknown (sRef_getType (fref)))
3978           {
3979             ; /* Okay, put in default values without knowing type */
3980           }
3981         else
3982           {
3983             /*@i#!@!!@*/
3984             DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
3985                       sRef_unparseFull (tref),
3986                       fkey));
3987           }
3988       }
3989     else
3990       {
3991         llassert (metaStateInfo_isDefined (minfo));
3992         
3993         if (stateValue_isError (fval) || stateValue_isError (tval))
3994           {
3995             ;
3996           }
3997         else if (sRef_isDefinitelyNull (fref)
3998                  || usymtab_isDefinitelyNull (fref))
3999           {
4000             ; /* No errors for null values in state transfers. */
4001           }
4002         
4003         else
4004           {
4005             stateCombinationTable sctable = metaStateInfo_getTransferTable (minfo);
4006             cstring msg = cstring_undefined;
4007             int nval = stateCombinationTable_lookup (sctable, 
4008                                                      stateValue_getValue (fval), 
4009                                                      stateValue_getValue (tval), 
4010                                                      &msg);
4011             
4012             if (nval == stateValue_error)
4013               {
4014                 if (transferType == TT_LEAVETRANS)
4015                   {
4016                     BADBRANCH;
4017                   }
4018                 else if (transferType == TT_GLOBRETURN)
4019                   {
4020                     if (optgenerror 
4021                         (FLG_STATETRANSFER,
4022                          message
4023                          ("Function returns with global %q in inconsistent state (%q is %q, should be %q)%q",
4024                           sRef_unparse (sRef_getRootBase (fref)),
4025                           sRef_unparse (fref),
4026                           stateValue_unparseValue (fval, minfo),
4027                           stateValue_unparseValue (tval, minfo),
4028                           cstring_isDefined (msg) 
4029                           ? message (": %s", msg) : cstring_undefined),
4030                          loc))
4031                       {
4032                         sRef_showMetaStateInfo (fref, fkey);
4033                       }             
4034                   }
4035                 else if (transferType == TT_GLOBPASS)
4036                   {
4037                     if (optgenerror 
4038                         (FLG_STATETRANSFER,
4039                          message
4040                          ("Function called with global %q in inconsistent state (%q is %q, should be %q)%q",
4041                           sRef_unparse (sRef_getRootBase (fref)),
4042                           stateValue_unparseValue (fval, minfo),
4043                           sRef_unparse (fref),
4044                           stateValue_unparseValue (tval, minfo),
4045                           cstring_isDefined (msg) 
4046                           ? message (": %s", msg) : cstring_undefined),
4047                          loc))
4048                       {
4049                         sRef_showMetaStateInfo (fref, fkey);
4050                       }             
4051                   }
4052                 else if (transferType == TT_PARAMRETURN)
4053                   {
4054                     if (optgenerror 
4055                         (FLG_STATETRANSFER,
4056                          message
4057                          ("Function returns with parameter %q in inconsistent state (%q is %q, should be %q)%q",
4058                           sRef_unparse (sRef_getRootBase (fref)),
4059                           sRef_unparse (fref),                  
4060                           stateValue_unparseValue (fval, minfo),
4061                           stateValue_unparseValue (tval, minfo),
4062                           cstring_isDefined (msg) 
4063                           ? message (": %s", msg) : cstring_undefined),
4064                          loc))
4065                       {
4066                         sRef_showMetaStateInfo (fref, fkey);
4067                       }
4068                   }
4069                 else
4070                   {
4071                     if (optgenerror 
4072                         (FLG_STATETRANSFER,
4073                          message
4074                          ("Invalid transfer from %q %x to %q (%q)%q",
4075                           stateValue_unparseValue (fval, minfo),
4076                           sRef_unparse (fref),
4077                           stateValue_unparseValue (tval, minfo),
4078                           sRef_unparse (tref),
4079                           cstring_isDefined (msg) 
4080                           ? message (": %s", msg) : cstring_undefined),
4081                          loc))
4082                       {
4083                         sRef_showMetaStateInfo (fref, fkey);
4084                       }
4085                   }
4086
4087               }
4088                     
4089             if (stateValue_getValue (fval) != nval)
4090               {
4091                 stateValue_updateValueLoc (fval, nval, loc);
4092               }
4093           }
4094       }
4095     
4096     DPRINTF (("Transfer: %s %s -> %s",
4097               fkey, stateValue_unparse (fval), stateValue_unparse (tval)));
4098   } end_valueTable_elements ;
4099 }
4100
4101 static void
4102 checkMetaStateTransfer (exprNode fexp, sRef fref, exprNode texp, sRef tref, 
4103                         exprNode fcn,
4104                         fileloc loc, transferKind /*@i32@*/ transferType)
4105 {
4106   valueTable fvalues = sRef_getValueTable (fref);
4107   valueTable tvalues = sRef_getValueTable (tref);
4108
4109   DPRINTF (("Metastate transfer: from %s", exprNode_unparse (fexp)));
4110   
4111   DPRINTF (("Metastate transfer: %s => %s",
4112             sRef_unparseFull (fref),
4113             sRef_unparseFull (tref)));
4114
4115   if (valueTable_isUndefined (tvalues) || valueTable_isUndefined (fvalues)) {
4116     /* Cannot check without value tables.  An error was already detected. */
4117     DPRINTF (("No value table: %s / %s",
4118               bool_unparse (valueTable_isUndefined (tvalues)),
4119               bool_unparse (valueTable_isUndefined (fvalues))));
4120     return;
4121   }
4122
4123   valueTable_elements (fvalues, fkey, fval) {
4124     stateValue tval;
4125     metaStateInfo minfo;
4126     stateCombinationTable sctable;
4127     cstring msg;
4128     int nval;
4129
4130     DPRINTF (("Transfer: %s", fkey));
4131     tval = valueTable_lookup (tvalues, fkey);
4132     minfo = context_lookupMetaStateInfo (fkey);
4133
4134     if (!stateValue_isDefined (tval)) 
4135       {
4136         if (ctype_isUnknown (sRef_getType (fref)))
4137           {
4138             ; /* Okay, put in default values without knowing type */
4139           }
4140         else
4141           {
4142             /*@i#!@!!@*/
4143             DPRINTF (("Metastate transfer: %s => %s",
4144                       exprNode_unparse (fexp), exprNode_unparse (texp)));
4145             DPRINTF (("Cannot find meta state for: %s / to: %s / %s", sRef_unparseFull (fref),
4146                       sRef_unparseFull (tref),
4147                       fkey));
4148           }
4149       }
4150     else
4151       {
4152         llassert (metaStateInfo_isDefined (minfo));
4153         
4154         if (stateValue_isError (fval))
4155           {
4156             ;
4157           }
4158         else if (stateValue_isError (tval))
4159           {
4160             if (sRef_isLocalVar (tref) && transferType == TT_DOASSIGN)
4161               {
4162                 /* Local assignments just replace state. */
4163                 stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
4164                 DPRINTF (("Update: %s", stateValue_unparse (tval)));
4165               }
4166             else if (transferType == TT_FCNRETURN)
4167               {
4168                 ; /* Returning from an unannotated function */
4169               }
4170             else
4171               {
4172                 DPRINTF (("Transfer to error: %s / %s", sRef_unparseFull (tref),
4173                           transferType_unparse (transferType)));
4174               }
4175           }
4176         else 
4177           {
4178             DPRINTF (("Check: %s / %s / %s / %s", fkey,
4179                       metaStateInfo_unparse (minfo),
4180                       stateValue_unparse (fval),
4181                       stateValue_unparse (tval)));
4182             
4183             sctable = metaStateInfo_getTransferTable (minfo);
4184             msg = cstring_undefined;
4185             
4186             nval = stateCombinationTable_lookup (sctable, 
4187                                                  stateValue_getValue (fval), 
4188                                                  stateValue_getValue (tval), 
4189                                                  &msg);
4190             
4191             if (transferType == TT_DOASSIGN && sRef_isLocalVar (tref))
4192               {
4193                 /* Local assignments just replace state. */
4194                 DPRINTF (("No transfer error assigning to local: %s", msg));
4195                 stateValue_updateValueLoc (tval, stateValue_getValue (fval), loc);
4196                 DPRINTF (("Update: %s", stateValue_unparse (tval)));
4197               }
4198             else
4199               {
4200                 if (nval == stateValue_error)
4201                   {
4202                     /*@i32 print extra info for assignments@*/
4203                     
4204                     if (optgenerror 
4205                         (FLG_STATETRANSFER,
4206                          message
4207                          ("Invalid transfer from %q %x to %q%q: %q",
4208                           stateValue_unparseValue (fval, minfo),
4209                           sRef_unparse (fref),
4210                           stateValue_unparseValue (tval, minfo),
4211                           cstring_isDefined (msg) 
4212                           ? message (" (%s)", msg) : cstring_undefined,
4213                           transferErrorExcerpt (transferType, fexp, texp, fcn)),
4214                          loc))
4215                       {
4216                         sRef_showMetaStateInfo (fref, fkey);
4217                         sRef_showMetaStateInfo (tref, fkey);
4218                       }
4219                     else
4220                       {
4221                         DPRINTF (("Suppressed transfer error: %s", msg));
4222                       }
4223                   }
4224                 else
4225                   {
4226                     if (transferType == TT_FCNRETURN)
4227                       {
4228                         /*
4229                         ** Returning this reference from a function, mark this reference
4230                         ** so no lost reference errors are returned.
4231                         */ 
4232
4233                         stateValue_updateValueLoc (fval, stateValue_error, loc);
4234                       }
4235                     else if (stateValue_getValue (fval) != nval)
4236                       {
4237                         stateValue_updateValueLoc (fval, nval, loc);
4238                       }
4239                     else
4240                       {
4241                         ;
4242                       }
4243                   }
4244               }
4245           }
4246       }
4247     
4248     DPRINTF (("Transfer: %s %s -> %s",
4249               fkey, stateValue_unparse (fval), stateValue_unparse (tval)));
4250   } end_valueTable_elements ;
4251 }
4252
4253 /*
4254 ** assigns fexp := tref or passes fexp as a parameter, or returns fexp.
4255 **
4256 ** For assignments, sets alias and definition state accordingly.
4257 */
4258
4259 static void
4260 checkTransfer (exprNode fexp, /*@dependent@*/ sRef fref, 
4261                exprNode texp, /*@dependent@*/ sRef tref, 
4262                exprNode fcn,
4263                fileloc loc, transferKind transferType)
4264 {
4265   setCodePoint ();
4266
4267   if (context_inProtectVars ())
4268     {
4269       return;
4270     }
4271   
4272   DPRINTF (("Check transfer: %s => %s",
4273             sRef_unparse (fref),
4274             sRef_unparse (tref)));
4275   DPRINTF (("Check transfer: %s => %s",
4276             exprNode_unparse (fexp),
4277             exprNode_unparse (texp)));
4278
4279   checkMetaStateTransfer (fexp, fref, texp, tref, fcn,
4280                           loc, transferType);
4281
4282   /*
4283   ** for local references, we need to check
4284   ** the transfer for all possible aliases.
4285   */
4286
4287   if (sRef_isLocalVar (tref) && transferType != TT_DOASSIGN)
4288     {    
4289       sRefSet alias = usymtab_allAliases (tref);
4290
4291       sRefSet_realElements (alias, atref)
4292         {
4293           sRef abase = sRef_getRootBase (atref);
4294
4295           if (sRef_isKnown (atref)
4296               && !sRef_isLocalVar (abase) 
4297               && !sRef_isExternal (abase))
4298             {
4299               atref = sRef_updateSref (atref);
4300
4301               if (sRef_hasName (atref))
4302                 {
4303                   if (!sRef_isNew (atref) 
4304                       && !sRef_sameName (tref, atref))
4305                     {
4306                       context_setAliasAnnote (atref, tref);
4307                     }
4308                   
4309                   checkTransferAux (fexp, fref, TRUE, 
4310                                     texp, atref, FALSE,
4311                                     loc, transferType);
4312                   
4313                   context_clearAliasAnnote ();
4314                 }
4315             }
4316         } end_sRefSet_realElements;
4317
4318       sRefSet_free (alias);
4319     }
4320
4321   if (sRef_isLocalVar (fref))
4322     {    
4323       sRefSet alias = usymtab_allAliases (fref);
4324
4325       sRefSet_realElements (alias, afref)
4326         {
4327           sRef abase = sRef_getRootBase (afref);
4328
4329           if (sRef_isKnown (afref) 
4330               && !sRef_isLocalVar (abase)
4331               && !sRef_isExternal (abase))
4332             {
4333               afref = sRef_updateSref (afref);
4334
4335               if (sRef_hasName (afref))
4336                 {
4337                   if (!sRef_isNew (afref) 
4338                       && !sRef_sameName (afref, fref))
4339                     {
4340                       context_setAliasAnnote (afref, fref);
4341                     }
4342                   
4343                   checkTransferAux (fexp, afref, FALSE,
4344                                     texp, tref, TRUE,
4345                                     loc, transferType);
4346                   
4347                   context_clearAliasAnnote ();
4348                 }
4349             }
4350         } end_sRefSet_realElements;
4351
4352       sRefSet_free (alias);
4353     }
4354   
4355   setCodePoint ();
4356   checkTransferAux (fexp, fref, FALSE, texp, tref, FALSE, 
4357                     loc, transferType);
4358   setCodePoint ();  
4359 }
4360
4361 static /*@exposed@*/ sRef 
4362   dependentReference (sRef sr)
4363 {
4364   sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4365
4366   DPRINTF (("Dependent reference: %s", sRef_unparse (sr)));
4367   DPRINTF (("Aliases: %s", sRefSet_unparse (ab)));
4368
4369   /*
4370   ** If there is a local variable that aliases sr, then there is no
4371   ** error.  Make the local an only.
4372   */
4373   
4374   if (!sRefSet_isEmpty (ab))
4375     {
4376       sRef res = sRef_undefined;
4377
4378       DPRINTF (("Here we are!"));
4379
4380       /*
4381       ** make one an only, others alias it
4382       */
4383                   
4384       sRefSet_realElements (ab, current)
4385         {
4386           if (sRef_isOwned (current))
4387             {
4388               res = current; 
4389               break;
4390             }
4391         } end_sRefSet_realElements;
4392
4393       if (sRef_isInvalid (res))
4394         {
4395           /* 
4396           ** evans - 2001-03-24
4397           ** No owned element, just choose one! 
4398           ** (Any reason for preference?)
4399           */
4400
4401           res = sRefSet_choose (ab);
4402         }
4403
4404       sRefSet_free (ab);
4405       return res;
4406     }
4407
4408   return sRef_undefined;
4409 }
4410
4411 bool canLoseReference (/*@dependent@*/ sRef sr, fileloc loc)
4412 {
4413   bool gotone = FALSE;
4414   sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4415     
4416   /*
4417   ** if there is a local variable that aliases sr, then there is no
4418   ** error.  Make the local an only.
4419   */
4420   
4421   if (!sRefSet_isEmpty (ab))
4422     {
4423       /*
4424       ** make one an only, others alias it
4425       */
4426       
4427       sRefSet_realElements (ab, current)
4428         {
4429           sRef_setLastReference (current, sr, loc);
4430           gotone = TRUE;
4431           break;
4432         } end_sRefSet_realElements;
4433
4434       sRefSet_free (ab);
4435     }
4436
4437   return gotone;
4438 }
4439
4440 bool canLoseLocalReference (/*@dependent@*/ sRef sr, fileloc loc)
4441 {
4442   bool gotone = FALSE;
4443   sRefSet ab = usymtab_aliasedBy (sr); /* yes, really mean aliasedBy */
4444     
4445   /*
4446   ** if there is a local variable that aliases sr, then there is no
4447   ** error.  Make the local an only.
4448   */
4449   
4450   if (!sRefSet_isEmpty (ab))
4451     {
4452       /*
4453       ** make one an only, others alias it
4454       */
4455       
4456       sRefSet_realElements (ab, current)
4457         {
4458           if (sRef_isRealLocalVar (sRef_getRootBase (current)))
4459             {
4460               sRef_setLastReference (current, sr, loc);
4461               gotone = TRUE;
4462               break;
4463             }
4464         } end_sRefSet_realElements;
4465
4466       sRefSet_free (ab);
4467     }
4468
4469   return gotone;
4470 }
This page took 1.463274 seconds and 5 git commands to generate.