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