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