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