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