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