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