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