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