]> andersk Git - splint.git/blame - src/exprChecks.c
Made allocations involving sizeof work correctly (test/malloc.c).
[splint.git] / src / exprChecks.c
CommitLineData
616915dd 1/*
11db3170 2** Splint - annotation-assisted static program checker
c59f5181 3** Copyright (C) 1994-2003 University of Virginia,
616915dd 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**
155af98d 20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
11db3170 22** For more information: http://www.splint.org
616915dd 23*/
24/*
25** exprChecks.c
26*/
27
1b8ae690 28# include "splintMacros.nf"
616915dd 29# include "basic.h"
30# include "cgrammar.h"
31# include "cgrammar_tokens.h"
28bf4b0b 32# include "transferChecks.h"
616915dd 33# include "exprChecks.h"
34
35/*
36** for now, allow exprChecks to access exprNode.
37** may remove this in future
38*/
39
40/*@access exprNode@*/
41
28bf4b0b 42static bool checkCallModifyAux (/*@exposed@*/ sRef p_s, exprNode p_f, sRef p_alias, exprNode p_err);
43static bool checkModifyValAux (/*@exposed@*/ sRef p_s, exprNode p_f, sRef p_alias, exprNode p_err);
44static bool checkModifyAux (/*@exposed@*/ sRef p_s, exprNode p_f, sRef p_alias, exprNode p_err);
616915dd 45static void checkSafeReturnExpr (/*@notnull@*/ exprNode p_e);
46
47/*
48** called at end of expression statement
49**
50** of e->kind is not an assign, empty, body or modop
51** verify the the value is void
52**
53*/
54
abd7f895 55static int inCompoundStatementExpression = 0;
56
57void
58exprChecks_inCompoundStatementExpression (void)
59{
60 inCompoundStatementExpression++;
61}
62
63void
64exprChecks_leaveCompoundStatementExpression (void)
65{
66 inCompoundStatementExpression--;
67 llassert (inCompoundStatementExpression >= 0);
68}
69
616915dd 70void
abd7f895 71exprChecks_checkStatementEffect (exprNode e)
616915dd 72{
73 bool hasError = FALSE;
74
abd7f895 75 if (inCompoundStatementExpression > 0)
76 {
77 /*
78 ** Okay to have effectless statments in compound statement expression (should check
79 ** it is the last statement, but we don't for now).
80 */
81
82 return;
83 }
84
616915dd 85 if (!exprNode_isError (e))
86 {
87 exprKind ek = e->kind;
88
89 if (ek == XPR_CALL && !(ctype_isRealVoid (e->typ)))
90 {
91 if (ctype_isKnown (e->typ))
92 {
93 if (ctype_isManifestBool (ctype_realishType (e->typ)))
94 {
95 hasError = optgenerror
96 (FLG_RETVALBOOL,
97 message ("Return value (type %t) ignored: %s",
98 e->typ,
99 exprNode_unparseFirst (e)),
100 e->loc);
101 }
102 else if (ctype_isDirectInt (e->typ))
103 {
104 hasError = optgenerror
105 (FLG_RETVALINT,
106 message ("Return value (type %t) ignored: %s",
107 e->typ,
108 exprNode_unparseFirst (e)),
109 e->loc);
110 }
111 else
112 {
113 hasError = optgenerror
114 (FLG_RETVALOTHER,
115 message ("Return value (type %t) ignored: %s",
116 e->typ,
117 exprNode_unparseFirst (e)),
118 e->loc);
119 }
120 }
121 }
122
123 if (!hasError && !(exprNode_mayEscape (e))
124 && !(e->canBreak)) /* control changes are effects too! */
125 {
126 if (sRefSet_hasRealElement (e->sets)
127 || sRefSet_hasRealElement (e->msets))
128 {
129 ; /* okay */
130 }
131 else
132 {
133 if (sRefSet_isEmpty (e->sets) && sRefSet_isEmpty (e->msets))
134 {
135 voptgenerror
136 (FLG_NOEFFECT,
137 message ("Statement has no effect: %s",
138 exprNode_unparseFirst (e)),
139 e->loc);
140 }
141 else
142 {
143 if (context_maybeSet (FLG_NOEFFECTUNCON))
144 {
145 if (sRefSet_hasUnconstrained (e->sets))
146 {
147 voptgenerror
148 (FLG_NOEFFECTUNCON,
149 message ("Statement has no effect (possible "
150 "undected modification through "
151 "call to %q): %s",
152 sRefSet_unparseUnconstrained (e->sets),
153 exprNode_unparseFirst (e)),
154 e->loc);
155 }
156 else if (sRefSet_hasUnconstrained (e->msets))
157 {
158 voptgenerror
159 (FLG_NOEFFECTUNCON,
160 message ("Statement has no effect (possible "
161 "undected modification through "
162 "call to %q): %s",
163 sRefSet_unparseUnconstrained (e->msets),
164 exprNode_unparseFirst (e)),
165 e->loc);
166 }
167 else
168 {
169 ; /* statement has unknown modification */
170 }
171 }
172 }
173 }
174 }
175 }
176}
177
178static bool
179checkRepExposed (sRef base, /*@notnull@*/ exprNode e, sRef alias,
180 /*@unused@*/ exprNode unused)
181{
182 ctype btype;
183
184 if (sRef_isInvalid (alias) || sRef_sameName (base, alias))
185 {
186 btype = sRef_getType (base);
187
188 if (ctype_isAbstract (btype) && ctype_isVisiblySharable (e->typ))
189 {
190 voptgenerror (FLG_RETEXPOSE,
191 message ("Return value exposes rep of %s: %s",
192 ctype_unparse (btype),
193 exprNode_unparse (e)),
194 e->loc);
195 return TRUE;
196 }
197 }
198 else
199 {
200 sRef rbase = sRef_getRootBase (base);
201 btype = sRef_getType (rbase);
202
203 if (ctype_isAbstract (btype) && ctype_isVisiblySharable (e->typ))
204 {
205 voptgenerror
206 (FLG_RETEXPOSE,
207 message ("Return value may expose rep of %s through alias %q: %s",
208 ctype_unparse (btype),
209 sRef_unparse (rbase),
210 exprNode_unparse (e)),
211 e->loc);
212 return TRUE;
213 }
214 }
215
216 return FALSE;
217}
218
219static bool
220checkRefGlobParam (sRef base, /*@notnull@*/ exprNode e,
221 sRef alias, /*@unused@*/ exprNode unused)
222{
223 if (sRef_isInvalid (alias) || sRef_sameName (base, alias))
224 {
225 ctype ct = e->typ;
226
227 if (ctype_isUnknown (ct))
228 {
229 ct = sRef_getType (base);
230 }
231
232 if (ctype_isVisiblySharable (ct))
233 {
28bf4b0b 234 if (sRef_isFileOrGlobalScope (base))
616915dd 235 {
28bf4b0b 236 uentry fcn = context_getHeader ();
237 bool noerror = FALSE;
238
239 if (uentry_isValid (fcn) && uentry_isFunction (fcn))
240 {
241 sRef res = uentry_getSref (fcn);
242
243 /* If result is dependent and global is owned, this is okay... */
244 if (sRef_isDependent (res)
245 && sRef_isOwned (base))
246 {
247 noerror = TRUE;
248
249 }
250 }
251
252 if (!noerror)
253 {
254 voptgenerror
255 (FLG_RETALIAS,
256 message ("Function returns reference to global %q: %s",
257 sRef_unparse (base),
258 exprNode_unparse (e)),
259 e->loc);
260 }
616915dd 261
262 return TRUE;
263 }
264 else if (sRef_isAnyParam (base))
265 {
266 uentryList params = context_getParams ();
51bc6ecc 267 int paramno = sRef_getParam (base);
616915dd 268
269 if (paramno < uentryList_size (params))
270 {
271 uentry arg = uentryList_getN (params, paramno);
272 sRef ref = uentry_getSref (arg);
b73d1009 273
616915dd 274 if (uentry_isReturned (arg)
275 || sRef_isOnly (ref)
276 || sRef_isExposed (ref)
277 || sRef_isRefCounted (ref))
278 {
279 ; /* okay */
280 }
281 else
282 {
283 voptgenerror
284 (FLG_RETALIAS,
285 message ("Function returns reference to parameter %q: %s",
286 sRef_unparse (base),
287 exprNode_unparse (e)),
288 e->loc);
289 }
290 }
291 else
292 {
293 llbuglit ("ret alias: bad paramno");
294 }
295
296 return TRUE;
297 }
298 else
299 {
300 return FALSE;
301 }
302 }
303 }
304 else
305 {
306 if (ctype_isVisiblySharable (e->typ))
307 {
28bf4b0b 308 if (sRef_isFileOrGlobalScope (base))
616915dd 309 {
310 voptgenerror
311 (FLG_RETALIAS,
312 message ("Function may return reference to global %q through alias %q: %s",
313 sRef_unparse (alias),
314 sRef_unparse (base),
315 exprNode_unparse (e)),
316 e->loc);
317 return TRUE;
318 }
319 else if (sRef_isAnyParam (base) && !(sRef_isOnly (base)))
320 {
321 uentryList params = context_getParams ();
51bc6ecc 322 int paramno = sRef_getParam (base);
616915dd 323
324 if (paramno < uentryList_size (params))
325 {
326 uentry arg = uentryList_getN (params, paramno);
327
328 if (!uentry_isReturned (arg))
329 {
330 voptgenerror
331 (FLG_RETALIAS,
332 message
333 ("Function may return reference to parameter %q through alias %q: %s",
334 sRef_unparse (base),
335 sRef_unparse (alias),
336 exprNode_unparse (e)),
337 e->loc);
338
339 return TRUE;
340 }
341 }
342 else
343 {
344 voptgenerror
345 (FLG_RETALIAS,
346 message
347 ("Function may return reference to parameter %q through alias %q: %s",
348 sRef_unparse (base),
349 sRef_unparse (alias),
350 exprNode_unparse (e)),
351 e->loc);
352
353 return TRUE;
354 }
355 }
356 else
357 {
358 return FALSE;
359 }
360 }
361 }
362 return FALSE;
363}
364
365
366void
367exprNode_checkModify (exprNode e, exprNode err)
368{
369 llassert (exprNode_isDefined (e));
370
371 DPRINTF (("Check modify: %s", exprNode_unparse (e)));
28bf4b0b 372
616915dd 373 if (sRef_isValid (e->sref))
374 {
375 sRef_aliasCheckPred (checkModifyAux, sRef_isReference, e->sref, e, err);
376 }
377}
378
379void
380exprNode_checkModifyVal (exprNode e, exprNode err)
381{
382 llassert (exprNode_isDefined (e));
383
384 DPRINTF (("Check modify val: %s", exprNode_unparse (e)));
385
386 if (sRef_isValid (e->sref))
387 {
388 sRef_aliasCheckPred (checkModifyValAux, sRef_isReference, e->sref, e, err);
389 }
390}
391
392void
393exprChecks_checkNullReturn (fileloc loc)
394{
395 if (!context_inRealFunction ())
396 {
397 /*
398 llmsg ("exprChecks_checkNullReturnExpr: not in function context");
399 */
400 return;
401 }
402 else
403 {
404 if (ctype_isFunction (context_currentFunctionType ()))
405 {
28bf4b0b 406 ctype tr = ctype_getReturnType (context_currentFunctionType ());
616915dd 407
408 if (!ctype_isFirstVoid (tr))
409 {
410 if (ctype_isUnknown (tr))
411 {
412 voptgenerror
bb7c2085 413 (FLG_EMPTYRETURN,
616915dd 414 cstring_makeLiteral ("Empty return in function declared to implicitly return int"),
415 loc);
416 }
417 else
418 {
bb7c2085 419 voptgenerror (FLG_EMPTYRETURN,
616915dd 420 message ("Empty return in function declared to return %t", tr),
421 loc);
422 }
423 }
424 }
425 }
426}
427
428void
429exprNode_checkReturn (exprNode e)
430{
431 if (!exprNode_isError (e))
432 {
433 if (!context_inRealFunction ())
434 {
435 if (context_inMacro ())
436 {
bb7c2085 437 llerror (FLG_MACRORETURN,
616915dd 438 message ("Macro %s uses return (not functional)",
439 context_inFunctionName ()));
440 }
441 else
442 {
443 /*
444 llbuglit ("exprNode_checkReturn: not in function context");
445 */
446 }
447 }
448 else
449 {
450 if (ctype_isFunction (context_currentFunctionType ()))
451 {
452 checkSafeReturnExpr (e);
453 }
454 else
455 {
456 ;
457 }
458 }
459 }
460}
461
462void
463exprNode_checkPred (cstring c, exprNode e)
464{
465 ctype ct;
466
467 if (exprNode_isError (e))
468 return;
469
470 ct = exprNode_getType (e);
471
472 if (exprNode_isAssign (e))
473 {
474 voptgenerror
475 (FLG_PREDASSIGN,
476 message ("Test expression for %s is assignment expression: %s",
477 c, exprNode_unparse (e)),
478 e->loc);
479 }
480
28bf4b0b 481 if (ctype_isRealBool (ct) || ctype_isUnknown (ct))
482 /* evs 2000-12-20 added || ctype_isUnknown to avoid spurious messages */
616915dd 483 {
484 ;
485 }
486 else if (ctype_isRealPointer (ct))
487 {
488 voptgenerror
489 (FLG_PREDBOOLPTR,
490 message ("Test expression for %s not %s, type %t: %s", c,
491 context_printBoolName (),
492 ct, exprNode_unparse (e)),
493 e->loc);
494 }
495 else if (ctype_isRealInt (ct))
496 {
497 voptgenerror
498 (FLG_PREDBOOLINT,
499 message ("Test expression for %s not %s, type %t: %s", c,
500 context_printBoolName (), ct, exprNode_unparse (e)),
501 e->loc);
502 }
503 else
504 {
505 voptgenerror
506 (FLG_PREDBOOLOTHERS,
507 message ("Test expression for %s not %s, type %t: %s", c,
508 context_printBoolName (), ct, exprNode_unparse (e)),
509 e->loc);
510 }
511}
512
513void
514exprChecks_checkUsedGlobs (globSet decl, globSet used)
515{
516 fileloc fl = uentry_whereSpecified (context_getHeader ());
517
518 if (fileloc_isUndefined (fl))
519 {
520 fl = uentry_whereDeclared (context_getHeader ());
521 }
522
523 globSet_allElements (decl, el)
524 {
525 if (!globSet_member (used, el))
526 {
527 if (sRef_isSpecInternalState (el)
528 || sRef_isNothing (el))
529 {
530 ;
531 }
532 else
533 {
534 cstring sname = sRef_unparse (el);
535
536 if (fileloc_isLib (fl))
537 {
538 voptgenerror (FLG_USEALLGLOBS,
539 message ("Global %s listed (%q) but not used",
540 sname, fileloc_unparse (fl)),
541 g_currentloc);
542 }
543 else
544 {
545 voptgenerror (FLG_USEALLGLOBS,
546 message ("Global %s listed but not used", sname),
547 fl);
548 }
549
550 cstring_free (sname);
551 }
552 }
553 } end_globSet_allElements;
554}
555
556void
557exprNode_checkAllMods (sRefSet mods, uentry ue)
558{
559 bool realParams = FALSE;
560 uentry le = context_getHeader ();
561 fileloc fl = uentry_whereSpecified (le);
562 uentryList specParamNames = uentryList_undefined;
563 uentryList paramNames = context_getParams ();
564
565 if (uentry_isFunction (le))
566 {
567 specParamNames = uentry_getParams (le);
568
569 if (uentryList_isUndefined (specParamNames))
570 {
571 ; /* unknown params */
572 }
573 else if (uentryList_size (paramNames) != uentryList_size (specParamNames))
574 {
575 llbug
576 (message ("exprNode_checkAllMods: parameter lists have different sizes: "
577 "%q (%d) / %q (%d)",
578 uentryList_unparse (paramNames),
579 uentryList_size (paramNames),
580 uentryList_unparse (specParamNames),
581 uentryList_size (specParamNames)));
582 }
583 else if (uentryList_size (paramNames) > 0
584 && !uentry_hasRealName (uentryList_getN (specParamNames, 0)))
585 {
586 /* loaded from a library */
587 }
588 else
589 {
590 realParams = TRUE;
591 }
592 }
593
594 sRefSet_allElements (mods, sr)
595 {
596 if (sRef_isNothing (sr) || sRef_isSpecState (sr))
597 {
598 ; /* should report on anything? */
599 }
600 else if (sRef_isInternalState (sr))
601 {
602 if (!sRef_isModified (sr))
603 {
604 if (sRefSet_hasStatic (mods))
605 {
606 ; /* okay */
607 }
608 else
609 {
610 if (optgenerror
611 (FLG_MUSTMOD,
612 message
613 ("Function %s specified to modify internal state "
614 "but no internal state is modified",
615 uentry_rawName (ue)),
616 uentry_whereLast (ue)))
617 {
618 uentry_showWhereSpecified (le);
619 }
620 }
621 }
622 }
623 else
624 {
625 if (!sRef_isModified (sr))
626 {
627 cstring sname = realParams ? sRef_unparse (sr) : sRef_unparse (sr);
628
629 if (fileloc_isLib (fl) && !realParams)
630 {
631 voptgenerror
632 (FLG_MUSTMOD,
633 message ("Suspect object listed (%q) in modifies "
634 "clause of %s not modified: %s",
635 fileloc_unparse (fl),
636 uentry_rawName (ue),
637 sname),
638 uentry_whereLast (ue));
639 }
640 else
641 {
642 if (optgenerror
643 (FLG_MUSTMOD,
644 message ("Suspect object listed in modifies of %s "
645 "not modified: %s",
646 uentry_rawName (ue),
647 sname),
648 uentry_whereLast (ue)))
649 {
650 uentry_showWhereSpecified (le);
651 }
652 }
653 cstring_free (sname);
654 }
655 }
656 } end_sRefSet_allElements;
657}
658
659void exprNode_checkMacroBody (/*@only@*/ exprNode e)
660{
661 if (!exprNode_isError (e))
662 {
663 uentry hdr;
664
665 if (!(context_inFunctionLike () || context_inMacroConstant ()
b7e84605 666 || context_inUnknownMacro ()))
616915dd 667 {
668 llcontbug
669 (message
670 ("exprNode_checkMacroBody: not in macro function or constant: %q",
671 context_unparse ()));
672 exprNode_free (e);
673 return;
674 }
675
676 hdr = context_getHeader ();
677
678 if (e->kind == XPR_STMTLIST || e->kind == XPR_BODY)
679 {
680 voptgenerror
681 (FLG_MACROSTMT,
682 message
683 ("Macro %q definition is statement list (recommend "
684 "do { ... } while (0) constuction to ensure multiple "
685 "statement macro is syntactic function)",
686 uentry_getName (hdr)),
687 fileloc_isDefined (e->loc) ? e->loc : g_currentloc);
688 }
689
690 if (context_inMacroConstant ())
691 {
692 ctype t = uentry_getType (hdr);
693
694 uentry_setDefined (hdr, e->loc);
695
696 if (!(exprNode_matchType (t, e)))
697 {
698 cstring uname = uentry_getName (hdr);
699
700 if (cstring_equal (uname, context_getTrueName ())
701 || cstring_equal (uname, context_getFalseName ()))
702 {
703 /*
704 ** We need to do something special to allow FALSE and TRUE
705 ** to be defined without reporting errors. This is a tad
706 ** bogus, but otherwise lots of things would break.
707 */
708
709
710 llassert (ctype_isManifestBool (t));
711 /* Should also check type of e is a reasonable (?) bool type. */
712 }
713 else
714 {
715 if (optgenerror
716 (FLG_INCONDEFS,
717 message
718 ("Constant %q specified as %s, but defined as %s: %s",
719 uentry_getName (hdr),
720 ctype_unparse (t),
721 ctype_unparse (e->typ),
722 exprNode_unparse (e)),
723 e->loc))
724 {
725 uentry_showWhereSpecified (hdr);
726 }
727 }
728
729 cstring_free (uname);
730 }
731 else
732 {
733 if (context_maybeSet (FLG_NULLSTATE)
734 && ctype_isUA(t)
735 && ctype_isRealPointer (t)
736 && exprNode_isNullValue (e))
737 {
738 uentry ue = usymtab_getTypeEntry (ctype_typeId (t));
739 sRef sr = uentry_getSref (ue);
740
741 if (!sRef_possiblyNull (sr))
742 {
743 vgenhinterror
744 (FLG_NULLSTATE,
745 message ("Constant %q of non-null type %s defined "
746 "as null: %s",
747 uentry_getName (hdr), ctype_unparse (t),
748 exprNode_unparse (e)),
749 message ("If %s can be null, add a /*@null@*/ "
750 "qualifer to its typedef.",
751 ctype_unparse (t)),
752 e->loc);
753 }
754
755 uentry_mergeConstantValue (hdr, e->val);
756 e->val = multiVal_undefined;
757 }
758 }
759 }
b7e84605 760 else if (context_inMacroFunction () || context_inUnknownMacro ())
616915dd 761 {
762 ctype rettype = context_getRetType ();
763
764 if (context_isMacroMissingParams ())
765 {
766 llassert (context_inMacroFunction ());
767
768 /*
769 ** # define newname oldname
770 **
771 ** newname is a function
772 ** specification of oldname should match
773 ** specification of newname.
774 */
775
776 if (!ctype_isFunction (e->typ))
777 {
778 voptgenerror
779 (FLG_INCONDEFS,
780 message ("Function %s defined by unparameterized "
781 "macro not corresponding to function",
782 context_inFunctionName ()),
783 e->loc);
784 }
785 else
786 {
787 uentry ue = exprNode_getUentry (e);
788
789 if (uentry_isValid (ue))
790 {
791 /*
792 ** Okay, for now --- should check for consistency
793 */
794 /*
795 ** uentry oldue = usymtab_lookup (cfname);
796 */
797
798 /* check var conformance here! */
799 }
800 else
801 {
802 voptgenerror
803 (FLG_INCONDEFS,
804 message ("Function %s defined by unparameterized "
805 "macro not corresponding to function",
806 context_inFunctionName ()),
807 e->loc);
808 }
809
28bf4b0b 810 e->typ = ctype_getReturnType (e->typ);
616915dd 811 rettype = e->typ; /* avoid aditional errors */
812 }
813 }
814
815 if (ctype_isVoid (rettype) || ctype_isUnknown (rettype))
816 {
817 ; /* don't complain when void macros have values */
818 }
819 else if (!exprNode_matchType (rettype, e))
820 {
821 if (optgenerror
822 (FLG_INCONDEFS,
823 message ("Function %q specified to return %s, "
824 "implemented as macro having type %s: %s",
825 uentry_getName (hdr),
826 ctype_unparse (rettype), ctype_unparse (e->typ),
827 exprNode_unparse (e)),
828 e->loc))
829 {
830 uentry_showWhereSpecified (hdr);
831 }
832 }
833 else
834 {
835 switch (e->kind)
836 {
837 /* these expressions have values: */
838 case XPR_PARENS: case XPR_ASSIGN:
839 case XPR_EMPTY: case XPR_VAR:
840 case XPR_OP: case XPR_POSTOP:
841 case XPR_PREOP: case XPR_CALL:
842 case XPR_SIZEOFT: case XPR_SIZEOF:
843 case XPR_ALIGNOFT: case XPR_ALIGNOF:
844 case XPR_CAST: case XPR_FETCH:
845 case XPR_COMMA: case XPR_COND:
846 case XPR_ARROW: case XPR_CONST:
847 case XPR_STRINGLITERAL: case XPR_NUMLIT:
848 case XPR_FACCESS: case XPR_OFFSETOF:
849
2e127cb8 850 transferChecks_return (e, hdr);
616915dd 851 break;
852
853 /* these expressions don't */
854 case XPR_LABEL:
855 case XPR_VAARG: case XPR_ITER:
856 case XPR_FOR: case XPR_FORPRED:
857 case XPR_GOTO: case XPR_CONTINUE:
858 case XPR_BREAK: case XPR_RETURN:
859 case XPR_NULLRETURN: case XPR_IF:
860 case XPR_IFELSE: case XPR_DOWHILE:
861 case XPR_WHILE: case XPR_STMT:
862 case XPR_STMTLIST: case XPR_SWITCH:
863 case XPR_INIT: case XPR_BODY:
864 case XPR_NODE: case XPR_ITERCALL:
865 case XPR_TOK: case XPR_CASE:
866 case XPR_FTCASE: case XPR_FTDEFAULT:
867 case XPR_DEFAULT: case XPR_WHILEPRED:
868 case XPR_BLOCK: case XPR_INITBLOCK:
869 if (optgenerror
870 (FLG_INCONDEFS,
871 message ("Function %q specified to return %s, "
872 "implemented as macro with no result: %s",
873 uentry_getName (hdr),
874 ctype_unparse (rettype),
875 exprNode_unparse (e)),
876 e->loc))
877 {
878 uentry_showWhereSpecified (hdr);
879 }
880 }
881 }
882
883 usymtab_checkFinalScope (FALSE);
884 }
885 else
886 {
887 llbug (message ("exprNode_checkMacroBody: not in macro function: %q", context_unparse ()));
888 }
889
890 exprNode_free (e);
891 }
892
893 context_exitFunction ();
894 return;
895}
896
897void exprNode_checkFunctionBody (exprNode body)
898{
899 if (!exprNode_isError (body))
900 {
901 bool noret = context_getFlag (FLG_NORETURN);
902 bool checkret = exprNode_mustEscape (body);
903
904 if (!checkret
905 && noret
906 && !exprNode_errorEscape (body)
907 && context_inRealFunction ()
908 && ctype_isFunction (context_currentFunctionType ()))
909 {
28bf4b0b 910 ctype tr = ctype_getReturnType (context_currentFunctionType ());
616915dd 911
912 if (!ctype_isFirstVoid (tr))
913 {
914 if (ctype_isUnknown (tr))
915 {
916 voptgenerror
917 (FLG_NORETURN,
918 cstring_makeLiteral ("Path with no return in function declared to implicity return int"),
919 g_currentloc);
920 }
921 else
922 {
923 voptgenerror
924 (FLG_NORETURN,
925 message ("Path with no return in function declared to return %t",
926 tr),
927 g_currentloc);
928 }
929 }
930 }
616915dd 931
932 if (!checkret)
933 {
934 context_returnFunction ();
935 }
936 }
937}
938/*drl modified */
939
470b7798 940
abd7f895 941void exprNode_checkFunction (/*@unused@*/ uentry ue, /*@only@*/ exprNode body)
616915dd 942{
8f299805 943 constraintList c, t, post;
2934b455 944 constraintList c2, fix;
bb25bea6 945 context_enterInnerContext ();
946
abd7f895 947 llassert (exprNode_isDefined (body));
4c02d8be 948
6317f163 949 DPRINTF (("Checking body: %s", exprNode_unparse (body)));
950
b7b694d6 951 /*
952 if we're not going to be printing any errors for buffer overflows
953 we can skip the checking to improve performance
954
955 FLG_DEBUGFUNCTIONCONSTRAINT controls wheather we perform the check anyway
e5f31c00 956 in order to find potential problems like assert failures and seg faults...
b7b694d6 957 */
4c02d8be 958
6317f163 959 if (!(context_getFlag (FLG_DEBUGFUNCTIONCONSTRAINT)
960 || context_getFlag (FLG_BOUNDSWRITE)
961 || context_getFlag (FLG_BOUNDSREAD)
962 || context_getFlag (FLG_LIKELYBOUNDSWRITE)
963 || context_getFlag (FLG_LIKELYBOUNDSREAD)
964 || context_getFlag (FLG_CHECKPOST)
965 || context_getFlag (FLG_ALLOCMISMATCH)))
966 {
967 exprNode_free (body);
968 context_exitInnerPlain();
969 return;
970 }
28bf4b0b 971
abd7f895 972 exprNode_generateConstraints (body); /* evans 2002-03-02: this should not be declared to take a
973 dependent... fix it! */
616915dd 974
ae133592 975 c = uentry_getFcnPreconditions (ue);
616915dd 976
ae133592 977 if (constraintList_isDefined (c))
bb7c2085 978 {
6317f163 979 DPRINTF (("Function preconditions are %s", constraintList_unparseDetailed (c)));
bb7c2085 980
ae133592 981 body->requiresConstraints =
982 constraintList_reflectChangesFreePre (body->requiresConstraints, c);
bb7c2085 983
984 c2 = constraintList_copy (c);
985 fix = constraintList_makeFixedArrayConstraints (body->uses);
986 c2 = constraintList_reflectChangesFreePre (c2, fix);
ae133592 987
bb7c2085 988 constraintList_free (fix);
989
990 if (context_getFlag (FLG_ORCONSTRAINT))
991 {
992 t = constraintList_reflectChangesOr (body->requiresConstraints, c2 );
993 }
994 else
995 {
996 t = constraintList_reflectChanges(body->requiresConstraints, c2);
997 }
998
999 constraintList_free (body->requiresConstraints);
ae133592 1000 DPRINTF ((message ("The body has the required constraints: %s", constraintList_unparseDetailed (t) ) ) );
bb7c2085 1001
1002 body->requiresConstraints = t;
1003
1004 t = constraintList_mergeEnsures (c, body->ensuresConstraints);
1005 constraintList_free(body->ensuresConstraints);
1006
1007 body->ensuresConstraints = t;
ae133592 1008
1009 DPRINTF ((message ("The body has the ensures constraints: %s", constraintList_unparseDetailed (t) ) ) );
bb7c2085 1010 constraintList_free(c2);
1011 }
1012
1013 if (constraintList_isDefined(c))
1014 {
1015 DPRINTF ((message ("The Function %s has the preconditions %s",
ae133592 1016 uentry_unparse(ue), constraintList_unparseDetailed(c))));
bb7c2085 1017 }
1018 else
1019 {
1020 DPRINTF((message ("The Function %s has no preconditions", uentry_unparse(ue))));
1021 }
1022
6317f163 1023 if (context_getFlag (FLG_IMPBOUNDSCONSTRAINTS))
bb7c2085 1024 {
6317f163 1025 constraintList implicitFcnConstraints = context_getImplicitFcnConstraints (ue);
1026
1027 if (constraintList_isDefined (implicitFcnConstraints))
bb7c2085 1028 {
6317f163 1029 DPRINTF (("Implicit constraints: %s", constraintList_unparse (implicitFcnConstraints)));
1030
bb7c2085 1031 body->requiresConstraints = constraintList_reflectChangesFreePre (body->requiresConstraints,
6317f163 1032 implicitFcnConstraints);
1033 constraintList_free (implicitFcnConstraints);
1034 }
1035 else
1036 {
1037 DPRINTF (("No implicit constraints"));
bb7c2085 1038 }
1039 }
1040
1041 body->requiresConstraints = constraintList_sort (body->requiresConstraints);
1042
1043 constraintList_printError(body->requiresConstraints, g_currentloc);
1044
1045 post = uentry_getFcnPostconditions (ue);
1046
1047 if (context_getFlag (FLG_CHECKPOST))
1048 {
1049 if (constraintList_isDefined (post))
1050 {
1051 constraintList post2;
1052
1053 DPRINTF ((message ("The declared function postconditions are %s \n\n\n\n\n",
ae133592 1054 constraintList_unparseDetailed (post) ) ) );
bb7c2085 1055
1056 post = constraintList_reflectChangesFreePre (post, body->ensuresConstraints);
1057
1058 post2 = constraintList_copy (post);
1059 fix = constraintList_makeFixedArrayConstraints (body->uses);
1060 post2 = constraintList_reflectChangesFreePre (post2, fix);
1061 constraintList_free(fix);
1062 if ( context_getFlag (FLG_ORCONSTRAINT) )
1063 {
1064 t = constraintList_reflectChangesOr (post2, body->ensuresConstraints);
1065 }
1066 else
1067 {
1068 t = constraintList_reflectChanges(post2, body->ensuresConstraints);
1069 }
1070
1071 constraintList_free(post2);
1072 constraintList_free(post);
1073 post = t;
8f299805 1074
bb7c2085 1075 printf("Unresolved post conditions\n");
1076 constraintList_printErrorPostConditions(post, g_currentloc);
1077 }
1078 }
1079
1080 if (constraintList_isDefined (post))
1081 {
1082 constraintList_free (post);
1083 }
8f299805 1084
02984642 1085 body->ensuresConstraints = constraintList_sort(body->ensuresConstraints);
0c91982e 1086
b7b694d6 1087 if ( context_getFlag (FLG_FUNCTIONPOST) )
1088 {
1089 constraintList_printError(body->ensuresConstraints, g_currentloc);
1090 }
616915dd 1091
b7b694d6 1092 /* ConPrint (message ("Unable to resolve function constraints:\n%s", constraintList_printDetailed(body->requiresConstraints) ), g_currentloc);
616915dd 1093
11db3170 1094 ConPrint (message ("Splint has found function post conditions:\n%s", constraintList_printDetailed(body->ensuresConstraints) ), g_currentloc);
616915dd 1095
b7b694d6 1096 printf ("The required constraints are:\n%s", constraintList_printDetailed(body->requiresConstraints) );
ae133592 1097 printf ("The ensures constraints are:\n%s", constraintList_unparseDetailed(body->ensuresConstraints) );
b7b694d6 1098 */
616915dd 1099
6317f163 1100 if (constraintList_isDefined (c))
bb25bea6 1101 constraintList_free(c);
4ab867d6 1102
1103 context_exitInnerPlain();
ae133592 1104
1105 /* is it okay not to free this? */
1106 DPRINTF (("Done checking constraints..."));
1107 exprNode_free (body);
1108}
616915dd 1109
1110void exprChecks_checkEmptyMacroBody (void)
1111{
1112 uentry hdr;
1113
1114 if (!(context_inFunctionLike () || context_inMacroConstant ()
b7e84605 1115 || context_inUnknownMacro ()))
616915dd 1116 {
1117 llcontbug
1118 (message ("exprNode_checkEmptyMacroBody: not in macro function or constant: %q",
1119 context_unparse ()));
1120 return;
1121 }
1122
1123 hdr = context_getHeader ();
1124
1125 beginLine ();
1126
1127 if (uentry_isFunction (hdr))
1128 {
1129 voptgenerror
1130 (FLG_MACROEMPTY,
1131 message
1132 ("Macro definition for %q is empty", uentry_getName (hdr)),
1133 g_currentloc);
1134
1135 usymtab_checkFinalScope (FALSE);
1136 }
1137
1138 context_exitFunction ();
1139 return;
1140}
1141
1142void exprNode_checkIterBody (/*@only@*/ exprNode body)
1143{
1144 context_exitAllClauses ();
1145
1146 context_exitFunction ();
1147 exprNode_free (body);
1148}
1149
1150void exprNode_checkIterEnd (/*@only@*/ exprNode body)
1151{
1152 context_exitAllClauses ();
1153 context_exitFunction ();
1154 exprNode_free (body);
1155}
1156
1157static
28bf4b0b 1158bool checkModifyAuxAux (/*@exposed@*/ sRef s, exprNode f, sRef alias, exprNode err)
616915dd 1159{
1160 bool hasMods = context_hasMods ();
1161 flagcode errCode = hasMods ? FLG_MODIFIES : FLG_MODNOMODS;
1162
1163 if (exprNode_isDefined (f))
1164 {
1165 f->sets = sRefSet_insert (f->sets, s);
1166 }
1167
1168 if (context_getFlag (FLG_MODIFIES)
1169 && (hasMods || context_getFlag (FLG_MODNOMODS)))
1170 {
1171 sRefSet mods = context_modList ();
28bf4b0b 1172
616915dd 1173 if (!sRef_canModify (s, mods))
1174 {
1175 sRef rb = sRef_getRootBase (s);
616915dd 1176
28bf4b0b 1177
1178 if (sRef_isFileOrGlobalScope (rb))
616915dd 1179 {
1180 if (!context_checkGlobMod (rb))
1181 {
28bf4b0b 1182 return FALSE;
616915dd 1183 }
1184 }
28bf4b0b 1185
616915dd 1186 if (sRef_isInvalid (alias) || sRef_sameName (s, alias))
1187 {
1188 if (sRef_isLocalVar (sRef_getRootBase (s)))
1189 {
1190 voptgenerror
1191 (errCode,
1192 message
1193 ("Undocumented modification of internal state (%q): %s",
1194 sRef_unparse (s), exprNode_unparse (err)),
1195 exprNode_isDefined (f) ? f->loc : g_currentloc);
1196 }
1197 else
1198 {
1199 if (sRef_isSystemState (s))
1200 {
1201 if (errCode == FLG_MODNOMODS)
1202 {
1203 if (context_getFlag (FLG_MODNOMODS))
1204 {
1205 errCode = FLG_MODFILESYSTEM;
1206 }
1207 }
1208 else
1209 {
1210 errCode = FLG_MODFILESYSTEM;
1211 }
1212 }
1213
1214 voptgenerror
1215 (errCode,
1216 message ("Undocumented modification of %q: %s",
1217 sRef_unparse (s), exprNode_unparse (err)),
1218 exprNode_isDefined (f) ? f->loc : g_currentloc);
1219 }
1220
1221 return TRUE;
1222 }
1223 else
1224 {
1225 if (sRef_isReference (s) && !sRef_isAddress (alias))
1226 {
1227 voptgenerror
1228 (errCode,
1229 message
1230 ("Possible undocumented modification of %q through alias %q: %s",
1231 sRef_unparse (s),
1232 sRef_unparse (alias),
1233 exprNode_unparse (err)),
1234 exprNode_isDefined (f) ? f->loc : g_currentloc);
1235 return TRUE;
1236 }
1237 }
1238 }
1239 }
1240 else
1241 {
1242 if (context_maybeSet (FLG_MUSTMOD))
1243 {
1244 (void) sRef_canModify (s, context_modList ());
1245 }
1246
1247 if (sRef_isRefsField (s))
1248 {
1249 sRef_setModified (s);
1250 }
1251 }
1252
1253 return FALSE;
1254}
1255
1256static
28bf4b0b 1257bool checkModifyAux (/*@exposed@*/ sRef s, exprNode f, sRef alias, exprNode err)
616915dd 1258{
1259 DPRINTF (("Check modify aux: %s", sRef_unparseFull (s)));
1260
1261 if (sRef_isReference (s) && sRef_isObserver (s)
1262 && context_maybeSet (FLG_MODOBSERVER))
1263 {
1264 cstring sname;
1265
1266 if (sRef_isPointer (s))
1267 {
1268 sRef base = sRef_getBase (s);
1269 sname = sRef_unparse (base);
1270 }
1271 else
1272 {
1273 if (sRef_isAddress (s))
1274 {
1275 sRef p = sRef_constructPointer (s);
1276 sname = sRef_unparse (p);
1277 }
1278 else
1279 {
1280 sname = sRef_unparse (s);
1281 }
1282 }
1283
1284 if (!sRef_isValid (alias) || sRef_sameName (s, alias))
1285 {
1286 if (sRef_isMeaningful (s))
1287 {
1288 if (optgenerror
1289 (FLG_MODOBSERVER,
1290 message ("Suspect modification of observer %s: %s",
1291 sname, exprNode_unparse (err)),
1292 exprNode_isDefined (f) ? f->loc : g_currentloc))
1293 {
1294 sRef_showExpInfo (s);
1295 }
1296 }
1297 else
1298 {
1299 voptgenerror
1300 (FLG_MODOBSERVER,
1301 message ("Suspect modification of observer returned by "
1302 "function call: %s",
1303 exprNode_unparse (err)),
1304 exprNode_isDefined (f) ? f->loc : g_currentloc);
1305 }
1306 }
1307 else
1308 {
1309 if (optgenerror
1310 (FLG_MODOBSERVER,
1311 message ("Suspect modification of observer %s through alias %q: %s",
1312 sname, sRef_unparse (alias), exprNode_unparse (err)),
1313 exprNode_isDefined (f) ? f->loc : g_currentloc))
1314 {
1315 sRef_showExpInfo (s);
1316 }
1317 }
1318
1319 cstring_free (sname);
1320 }
1321
1322 (void) checkModifyAuxAux (s, f, alias, err);
1323 return FALSE;
1324}
1325
1326static
28bf4b0b 1327bool checkModifyValAux (/*@exposed@*/ sRef s, exprNode f, sRef alias, exprNode err)
616915dd 1328{
1329 (void) checkModifyAuxAux (s, f, alias, err);
1330 return FALSE;
1331}
1332
1333static
28bf4b0b 1334bool checkCallModifyAux (/*@exposed@*/ sRef s, exprNode f, sRef alias, exprNode err)
616915dd 1335{
1336 bool result = FALSE;
1337
28bf4b0b 1338 DPRINTF (("Check modify aux: %s / %s",
1339 sRef_unparse (s), sRef_unparse (alias)));
1340
616915dd 1341 if (sRef_isObserver (s) && context_maybeSet (FLG_MODOBSERVER))
1342 {
1343 sRef p = sRef_isAddress (s) ? sRef_constructPointer (s) : s;
1344 cstring sname = sRef_unparse (p);
1345
1346 if (!sRef_isValid (alias) || sRef_sameName (s, alias))
1347 {
1348 if (sRef_isMeaningful (s))
1349 {
1350 result = optgenerror
1351 (FLG_MODOBSERVER,
1352 message ("Suspect modification of observer %s: %s",
1353 sname, exprNode_unparse (err)),
1354 exprNode_isDefined (f) ? f->loc : g_currentloc);
1355 }
1356 else
1357 {
1358 result = optgenerror
1359 (FLG_MODOBSERVER,
1360 message ("Suspect modification of observer returned by "
1361 "function call: %s",
1362 exprNode_unparse (err)),
1363 exprNode_isDefined (f) ? f->loc : g_currentloc);
1364 }
1365 }
1366 else
1367 {
1368 result = optgenerror
1369 (FLG_MODOBSERVER,
1370 message
1371 ("Suspect modification of observer %s through alias %q: %s",
1372 sname, sRef_unparse (alias), exprNode_unparse (err)),
1373 exprNode_isDefined (f) ? f->loc : g_currentloc);
1374 }
1375
1376 cstring_free (sname);
1377 }
1378 else if (context_maybeSet (FLG_MODIFIES))
1379 {
28bf4b0b 1380 DPRINTF (("can modify: %s / %s",
1381 sRef_unparse (s),
1382 sRefSet_unparse (context_modList ())));
1383
616915dd 1384 if (!(sRef_canModifyVal (s, context_modList ())))
1385 {
1386 sRef p = sRef_isAddress (s) ? sRef_constructPointer (s) : s;
1387 cstring sname = sRef_unparse (p);
1388 bool hasMods = context_hasMods ();
1389 sRef rb = sRef_getRootBase (s);
1390 flagcode errCode = hasMods ? FLG_MODIFIES : FLG_MODNOMODS;
1391 bool check = TRUE;
28bf4b0b 1392
1393 DPRINTF (("Can't modify! %s", sRef_unparse (s)));
1394
1395 if (sRef_isFileOrGlobalScope (rb))
616915dd 1396 {
1397 uentry ue = sRef_getUentry (rb);
1398
1399 /* be more specific here! */
1400 if (!uentry_isCheckedModify (ue))
1401 {
1402 check = FALSE;
1403 }
1404 }
1405
1406 if (check)
1407 {
1408 if (!sRef_isValid (alias) || sRef_sameName (s, alias))
1409 {
1410 if (sRef_isLocalVar (sRef_getRootBase (s)))
1411 {
1412 voptgenerror
1413 (errCode,
1414 message
1415 ("Undocumented modification of internal "
1416 "state (%q) through call to %s: %s",
1417 sRef_unparse (s), exprNode_unparse (f),
1418 exprNode_unparse (err)),
1419 exprNode_isDefined (f) ? f->loc : g_currentloc);
1420 }
1421 else
1422 {
1423 if (sRef_isSystemState (s))
1424 {
1425 if (errCode == FLG_MODNOMODS)
1426 {
1427 if (context_getFlag (FLG_MODNOMODS))
1428 {
1429 errCode = FLG_MODFILESYSTEM;
1430 }
1431 }
1432 else
1433 {
1434 errCode = FLG_MODFILESYSTEM;
1435 }
1436 }
1437
1438 result = optgenerror
1439 (errCode,
1440 message ("Undocumented modification of %s "
1441 "possible from call to %s: %s",
1442 sname,
1443 exprNode_unparse (f),
1444 exprNode_unparse (err)),
1445 exprNode_isDefined (f) ? f->loc : g_currentloc);
1446 }
1447 }
1448 else
1449 {
1450 result = optgenerror
1451 (errCode,
1452 message ("Undocumented modification of %s possible "
1453 "from call to %s (through alias %q): %s",
1454 sname,
1455 exprNode_unparse (f),
1456 sRef_unparse (alias),
1457 exprNode_unparse (err)),
1458 exprNode_isDefined (f) ? f->loc : g_currentloc);
1459 }
1460 }
1461 cstring_free (sname);
1462 }
1463 }
1464 else
1465 {
1466 if (context_maybeSet (FLG_MUSTMOD))
1467 {
1468 (void) sRef_canModifyVal (s, context_modList ());
1469 }
1470 }
1471
1472 return result;
1473}
1474
1475void exprNode_checkCallModifyVal (sRef s, exprNodeList args, exprNode f, exprNode err)
1476{
1477 s = sRef_fixBaseParam (s, args);
28bf4b0b 1478 DPRINTF (("Check call modify: %s", sRef_unparse (s)));
616915dd 1479 sRef_aliasCheckPred (checkCallModifyAux, NULL, s, f, err);
1480}
1481
1482void
1483exprChecks_checkExport (uentry e)
1484{
1485 if (context_checkExport (e))
1486 {
1487 fileloc fl = uentry_whereDeclared (e);
1488
1489 if (fileloc_isHeader (fl) && !fileloc_isLib (fl)
1490 && !fileloc_isImport (fl) && !uentry_isStatic (e))
1491 {
1492 if (uentry_isFunction (e) ||
1493 (uentry_isVariable (e) && ctype_isFunction (uentry_getType (e))))
1494 {
1495 voptgenerror
1496 (FLG_EXPORTFCN,
1497 message ("Function exported, but not specified: %q",
1498 uentry_getName (e)),
1499 fl);
1500 }
1501 else if (uentry_isExpandedMacro (e))
1502 {
1503 voptgenerror
1504 (FLG_EXPORTMACRO,
1505 message ("Expanded macro exported, but not specified: %q",
1506 uentry_getName (e)),
1507 fl);
1508 }
1509 else if (uentry_isVariable (e) && !uentry_isParam (e))
1510 {
1511 voptgenerror
1512 (FLG_EXPORTVAR,
1513 message ("Variable exported, but not specified: %q",
1514 uentry_getName (e)),
1515 fl);
1516 }
1517 else if (uentry_isEitherConstant (e))
1518 {
1519 voptgenerror
1520 (FLG_EXPORTCONST,
1521 message ("Constant exported, but not specified: %q",
1522 uentry_getName (e)),
1523 fl);
1524 }
1525 else if (uentry_isIter (e) || uentry_isEndIter (e))
1526 {
1527 voptgenerror
1528 (FLG_EXPORTITER,
1529 message ("Iterator exported, but not specified: %q",
1530 uentry_getName (e)),
1531 fl);
1532 }
1533
1534 else if (uentry_isDatatype (e))
1535 {
1536 ; /* error already reported */
1537 }
1538 else
1539 {
1540 BADEXIT;
1541 }
1542 }
1543 }
1544}
1545
1546static void checkSafeReturnExpr (/*@notnull@*/ exprNode e)
1547{
28bf4b0b 1548 ctype tr = ctype_getReturnType (context_currentFunctionType ());
616915dd 1549 ctype te = exprNode_getType (e);
1550
b7e84605 1551 /* evans 2001-08-21: added test to warn about void returns from void functions */
1552 if (ctype_isVoid (tr))
1553 {
1554 (void) gentypeerror
1555 (te, e, tr, exprNode_undefined,
1556 message ("Return expression from function declared void: %s", exprNode_unparse (e)),
1557 e->loc);
1558 return;
1559 }
1560
616915dd 1561 if (!ctype_forceMatch (tr, te) && !exprNode_matchLiteral (tr, e))
1562 {
1563 (void) gentypeerror
1564 (te, e, tr, exprNode_undefined,
1565 message ("Return value type %t does not match declared type %t: %s",
1566 te, tr, exprNode_unparse (e)),
1567 e->loc);
1568 }
1569 else
1570 {
1571 sRef ret = e->sref;
1572 uentry rval = context_getHeader ();
1573 sRef resultref = uentry_getSref (rval);
1574
28bf4b0b 1575 DPRINTF (("Check return: %s / %s / %s",
1576 exprNode_unparse (e),
1577 sRef_unparseFull (e->sref),
1578 uentry_unparse (rval)));
1579
2e127cb8 1580 transferChecks_return (e, rval);
616915dd 1581
28bf4b0b 1582 DPRINTF (("After return: %s / %s / %s",
1583 exprNode_unparse (e),
1584 sRef_unparseFull (e->sref),
1585 uentry_unparse (rval)));
1586
616915dd 1587 if (!(sRef_isExposed (uentry_getSref (context_getHeader ()))
1588 || sRef_isObserver (uentry_getSref (context_getHeader ())))
1589 && (context_getFlag (FLG_RETALIAS)
1590 || context_getFlag (FLG_RETEXPOSE)))
1591 {
1592 sRef base = sRef_getRootBase (ret);
1593 ctype rtype = e->typ;
1594
1595 if (ctype_isUnknown (rtype))
1596 {
1597 rtype = tr;
1598 }
1599
1600 if (ctype_isVisiblySharable (rtype))
1601 {
1602 if (context_getFlag (FLG_RETALIAS))
1603 {
1604 sRef_aliasCheckPred (checkRefGlobParam, NULL, base,
1605 e, exprNode_undefined);
1606 }
1607
1608 if (context_getFlag (FLG_RETEXPOSE) && sRef_isIReference (ret)
1609 && !sRef_isExposed (resultref) && !sRef_isObserver (resultref))
1610 {
1611 sRef_aliasCheckPred (checkRepExposed, NULL, base, e,
1612 exprNode_undefined);
1613 }
1614 }
1615 }
1616 }
1617}
1618
28bf4b0b 1619
1620
1621
1622
This page took 0.287482 seconds and 5 git commands to generate.