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