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