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