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