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