]> andersk Git - splint.git/blob - src/exprChecks.c
ae0ed4f0d57334f470dfb257e09e814c9919db18
[splint.git] / src / exprChecks.c
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** exprChecks.c
26 */
27
28 # include "splintMacros.nf"
29 # include "basic.h"
30 # include "cgrammar.h"
31 # include "cgrammar_tokens.h"
32 # include "transferChecks.h"
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
42 static bool checkCallModifyAux (/*@exposed@*/ sRef p_s, exprNode p_f, sRef p_alias, exprNode p_err);
43 static bool checkModifyValAux (/*@exposed@*/ sRef p_s, exprNode p_f, sRef p_alias, exprNode p_err);
44 static bool checkModifyAux (/*@exposed@*/ sRef p_s, exprNode p_f, sRef p_alias, exprNode p_err);
45 static 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
55 static int inCompoundStatementExpression = 0;
56
57 void
58 exprChecks_inCompoundStatementExpression (void)
59 {
60   inCompoundStatementExpression++;
61 }
62
63 void
64 exprChecks_leaveCompoundStatementExpression (void)
65 {
66   inCompoundStatementExpression--;
67   llassert (inCompoundStatementExpression >= 0);
68 }
69
70 void
71 exprChecks_checkStatementEffect (exprNode e)
72 {
73   bool hasError = FALSE;
74
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
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
178 static bool
179 checkRepExposed (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
219 static bool
220 checkRefGlobParam (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         {
234           if (sRef_isFileOrGlobalScope (base))
235             {
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                 }
261
262               return TRUE;
263             }
264           else if (sRef_isAnyParam (base))
265             {
266               uentryList params = context_getParams ();
267               int paramno = sRef_getParam (base);
268
269               if (paramno < uentryList_size (params))
270                 {
271                   uentry arg = uentryList_getN (params, paramno);
272                   sRef ref = uentry_getSref (arg);
273                   
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         {
308           if (sRef_isFileOrGlobalScope (base))
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 ();
322               int paramno = sRef_getParam (base);
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
366 void
367 exprNode_checkModify (exprNode e, exprNode err)
368 {
369   llassert (exprNode_isDefined (e));
370
371   DPRINTF (("Check modify: %s", exprNode_unparse (e)));
372   
373   if (sRef_isValid (e->sref))
374     {
375       sRef_aliasCheckPred (checkModifyAux, sRef_isReference, e->sref, e, err);
376     }
377 }
378
379 void
380 exprNode_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
392 void
393 exprChecks_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         {
406           ctype tr = ctype_getReturnType (context_currentFunctionType ());
407
408           if (!ctype_isFirstVoid (tr))
409             {
410               if (ctype_isUnknown (tr))
411                 {
412                   voptgenerror
413                     (FLG_EMPTYRETURN,
414                      cstring_makeLiteral ("Empty return in function declared to implicitly return int"),
415                      loc);
416                 }
417               else
418                 {
419                   voptgenerror (FLG_EMPTYRETURN,
420                                 message ("Empty return in function declared to return %t", tr),
421                                 loc);
422                 }
423             }
424         }
425     }
426 }
427
428 void
429 exprNode_checkReturn (exprNode e)
430 {
431   if (!exprNode_isError (e))
432     {
433       if (!context_inRealFunction ())
434         {
435           if (context_inMacro ())
436             {
437               llerror (FLG_MACRORETURN,
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
462 void
463 exprNode_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
481   if (ctype_isRealBool (ct) || ctype_isUnknown (ct)) 
482          /* evs 2000-12-20 added || ctype_isUnknown to avoid spurious messages */
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
513 void
514 exprChecks_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
556 void
557 exprNode_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
659 void exprNode_checkMacroBody (/*@only@*/ exprNode e)
660 {
661   if (!exprNode_isError (e))
662     {
663       uentry hdr;
664
665       if (!(context_inFunctionLike () || context_inMacroConstant ()
666             || context_inUnknownMacro ()))
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         }
760       else if (context_inMacroFunction () || context_inUnknownMacro ())
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                   
810                   e->typ = ctype_getReturnType (e->typ);
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
850                   transferChecks_return (e, hdr);
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
897 void 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         {
910           ctype tr = ctype_getReturnType (context_currentFunctionType ());
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         }
931       
932       if (!checkret)
933         {
934           context_returnFunction ();
935         }
936     }
937 }
938 /*drl modified */
939
940
941 void exprNode_checkFunction (/*@unused@*/ uentry ue, /*@only@*/ exprNode body)
942 {
943   constraintList c, t, post;
944   constraintList c2, fix;
945   constraintList implicitFcnConstraints;
946   context_enterInnerContext ();
947
948   llassert (exprNode_isDefined (body));
949
950   /*
951     if we're not going to be printing any errors for buffer overflows
952     we can skip the checking to improve performance
953     
954     FLG_DEBUGFUNCTIONCONSTRAINT controls wheather we perform the check anyway
955     in order to find potential problems like assert failures and seg faults...
956   */
957
958   if (!context_getFlag(FLG_DEBUGFUNCTIONCONSTRAINT))
959     {
960       /* check if errors will printed */
961       if (!(context_getFlag(FLG_DEBUGFUNCTIONCONSTRAINT) ||
962             context_getFlag(FLG_BOUNDSWRITE) ||
963             context_getFlag(FLG_BOUNDSREAD)  ||
964             context_getFlag(FLG_LIKELYBOUNDSWRITE) ||
965             context_getFlag(FLG_LIKELYBOUNDSREAD)  ||
966             context_getFlag(FLG_CHECKPOST) ))
967         {
968           exprNode_free (body);
969           context_exitInnerPlain();
970           
971           return;
972         }
973     }
974   
975   exprNode_generateConstraints (body); /* evans 2002-03-02: this should not be declared to take a
976                                           dependent... fix it! */
977   
978   c =   uentry_getFcnPreconditions (ue);
979   DPRINTF(("function constraints\n"));
980   DPRINTF (("\n\n\n\n\n\n\n"));
981   
982   if (constraintList_isDefined(c) )
983     {
984       DPRINTF ((message ("Function preconditions are %s \n\n\n\n\n", constraintList_printDetailed (c) ) ) );
985       
986       body->requiresConstraints = constraintList_reflectChangesFreePre (body->requiresConstraints, c);
987       
988       c2  =  constraintList_copy (c);
989       fix =  constraintList_makeFixedArrayConstraints (body->uses);
990       c2  =  constraintList_reflectChangesFreePre (c2, fix);
991       constraintList_free (fix);
992       
993       if (context_getFlag (FLG_ORCONSTRAINT))
994         {
995           t = constraintList_reflectChangesOr (body->requiresConstraints, c2 );
996         }
997       else
998         {
999           t = constraintList_reflectChanges(body->requiresConstraints, c2);
1000         }
1001       
1002       constraintList_free (body->requiresConstraints);
1003       DPRINTF ((message ("The body has the required constraints: %s", constraintList_printDetailed (t) ) ) );
1004       
1005       body->requiresConstraints = t;
1006       
1007       t = constraintList_mergeEnsures (c, body->ensuresConstraints);
1008       constraintList_free(body->ensuresConstraints);
1009       
1010       body->ensuresConstraints = t;
1011       
1012       DPRINTF ((message ("The body has the ensures constraints: %s", constraintList_printDetailed (t) ) ) );
1013       constraintList_free(c2);
1014     }
1015   
1016   if (constraintList_isDefined(c))
1017     {
1018       DPRINTF ((message ("The Function %s has the preconditions %s", 
1019                          uentry_unparse(ue), constraintList_printDetailed(c))));
1020     }
1021   else
1022     {
1023       DPRINTF((message ("The Function %s has no preconditions", uentry_unparse(ue))));
1024     }
1025   
1026   implicitFcnConstraints = getImplicitFcnConstraints();
1027   
1028   if (constraintList_isDefined(implicitFcnConstraints) )
1029     {
1030       if (context_getFlag (FLG_IMPLICTCONSTRAINT) )
1031         {
1032           body->requiresConstraints = constraintList_reflectChangesFreePre (body->requiresConstraints, 
1033                                                                             implicitFcnConstraints );
1034         }
1035     }
1036   
1037   body->requiresConstraints = constraintList_sort (body->requiresConstraints);
1038   
1039   constraintList_printError(body->requiresConstraints, g_currentloc);
1040   
1041   post = uentry_getFcnPostconditions (ue);
1042   
1043   if (context_getFlag (FLG_CHECKPOST))
1044     {
1045       if (constraintList_isDefined (post))
1046         {
1047           constraintList post2;
1048           
1049           DPRINTF ((message ("The declared function postconditions are %s \n\n\n\n\n", 
1050                              constraintList_printDetailed (post) ) ) );
1051           
1052           post = constraintList_reflectChangesFreePre (post, body->ensuresConstraints);
1053           
1054           post2  =  constraintList_copy (post);
1055           fix =  constraintList_makeFixedArrayConstraints (body->uses);
1056           post2  =  constraintList_reflectChangesFreePre (post2, fix);
1057           constraintList_free(fix);
1058           if ( context_getFlag (FLG_ORCONSTRAINT) )
1059             {
1060               t = constraintList_reflectChangesOr (post2, body->ensuresConstraints);
1061             }
1062           else
1063             {
1064               t = constraintList_reflectChanges(post2, body->ensuresConstraints);
1065             }
1066           
1067           constraintList_free(post2);
1068           constraintList_free(post);
1069           post = t;
1070
1071           printf("Unresolved post conditions\n");
1072           constraintList_printErrorPostConditions(post, g_currentloc);
1073         }
1074     }
1075   
1076   if (constraintList_isDefined (post))
1077     {
1078       constraintList_free (post);
1079     }
1080    
1081    body->ensuresConstraints = constraintList_sort(body->ensuresConstraints);
1082
1083    if ( context_getFlag (FLG_FUNCTIONPOST) )
1084      {
1085        constraintList_printError(body->ensuresConstraints, g_currentloc);
1086      }
1087    
1088    /*   ConPrint (message ("Unable to resolve function constraints:\n%s", constraintList_printDetailed(body->requiresConstraints) ), g_currentloc);
1089
1090         ConPrint (message ("Splint has found function post conditions:\n%s", constraintList_printDetailed(body->ensuresConstraints) ), g_currentloc);
1091   
1092         printf ("The required constraints are:\n%s", constraintList_printDetailed(body->requiresConstraints) );
1093         printf ("The ensures constraints are:\n%s", constraintList_printDetailed(body->ensuresConstraints) );
1094    */
1095    
1096    if (constraintList_isDefined(c) )
1097      constraintList_free(c);
1098
1099    context_exitInnerPlain();
1100
1101    /*is it okay not to free this?*/
1102   exprNode_free (body);
1103   }
1104
1105 void exprChecks_checkEmptyMacroBody (void)
1106 {
1107   uentry hdr;
1108   
1109   if (!(context_inFunctionLike () || context_inMacroConstant ()
1110         || context_inUnknownMacro ()))
1111     {
1112       llcontbug 
1113         (message ("exprNode_checkEmptyMacroBody: not in macro function or constant: %q", 
1114                   context_unparse ()));
1115       return;
1116     }
1117   
1118   hdr = context_getHeader ();
1119   
1120   beginLine ();
1121   
1122   if (uentry_isFunction (hdr))
1123     {
1124       voptgenerror 
1125         (FLG_MACROEMPTY,
1126          message 
1127          ("Macro definition for %q is empty", uentry_getName (hdr)),
1128          g_currentloc);
1129
1130       usymtab_checkFinalScope (FALSE);
1131     }
1132
1133   context_exitFunction ();
1134   return;
1135 }
1136
1137 void exprNode_checkIterBody (/*@only@*/ exprNode body)
1138 {
1139   context_exitAllClauses ();
1140
1141   context_exitFunction ();
1142   exprNode_free (body);
1143 }
1144
1145 void exprNode_checkIterEnd (/*@only@*/ exprNode body)
1146 {
1147   context_exitAllClauses ();
1148   context_exitFunction ();
1149   exprNode_free (body);
1150 }
1151
1152 static
1153 bool checkModifyAuxAux (/*@exposed@*/ sRef s, exprNode f, sRef alias, exprNode err)
1154 {
1155   bool hasMods = context_hasMods ();
1156   flagcode errCode = hasMods ? FLG_MODIFIES : FLG_MODNOMODS;
1157
1158   if (exprNode_isDefined (f))
1159     {
1160       f->sets = sRefSet_insert (f->sets, s); 
1161     }
1162
1163   if (context_getFlag (FLG_MODIFIES) 
1164       && (hasMods || context_getFlag (FLG_MODNOMODS)))
1165     {
1166       sRefSet mods = context_modList ();
1167
1168       if (!sRef_canModify (s, mods))
1169         {
1170           sRef rb = sRef_getRootBase (s);
1171           
1172           
1173           if (sRef_isFileOrGlobalScope (rb))
1174             {
1175               if (!context_checkGlobMod (rb))
1176                 {
1177                   return FALSE;
1178                 }
1179             }
1180           
1181           if (sRef_isInvalid (alias) || sRef_sameName (s, alias))
1182             {
1183               if (sRef_isLocalVar (sRef_getRootBase (s)))
1184                 {
1185                   voptgenerror 
1186                     (errCode,
1187                      message 
1188                      ("Undocumented modification of internal state (%q): %s", 
1189                       sRef_unparse (s), exprNode_unparse (err)), 
1190                      exprNode_isDefined (f) ? f->loc : g_currentloc);
1191                 }
1192               else
1193                 {
1194                   if (sRef_isSystemState (s))
1195                     {
1196                       if (errCode == FLG_MODNOMODS) 
1197                         {
1198                           if (context_getFlag (FLG_MODNOMODS))
1199                             {
1200                               errCode = FLG_MODFILESYSTEM;
1201                             }
1202                         }
1203                       else
1204                         {
1205                           errCode = FLG_MODFILESYSTEM;
1206                         }
1207                     }
1208
1209                   voptgenerror 
1210                     (errCode,
1211                      message ("Undocumented modification of %q: %s", 
1212                               sRef_unparse (s), exprNode_unparse (err)), 
1213                      exprNode_isDefined (f) ? f->loc : g_currentloc);
1214                 }
1215               
1216               return TRUE;
1217             }
1218           else
1219             {
1220               if (sRef_isReference (s) && !sRef_isAddress (alias))
1221                 {
1222                   voptgenerror 
1223                     (errCode,
1224                      message
1225                      ("Possible undocumented modification of %q through alias %q: %s", 
1226                       sRef_unparse (s),
1227                       sRef_unparse (alias),
1228                       exprNode_unparse (err)),
1229                      exprNode_isDefined (f) ? f->loc : g_currentloc);
1230                   return TRUE;
1231                 }
1232             }
1233         }
1234     }
1235   else
1236     {
1237       if (context_maybeSet (FLG_MUSTMOD))
1238         {
1239           (void) sRef_canModify (s, context_modList ());
1240         }
1241       
1242       if (sRef_isRefsField (s))
1243         {
1244           sRef_setModified (s);
1245         }
1246     }
1247   
1248   return FALSE;
1249 }
1250
1251 static
1252 bool checkModifyAux (/*@exposed@*/ sRef s, exprNode f, sRef alias, exprNode err)
1253 {
1254   DPRINTF (("Check modify aux: %s", sRef_unparseFull (s)));
1255
1256   if (sRef_isReference (s) && sRef_isObserver (s) 
1257       && context_maybeSet (FLG_MODOBSERVER))
1258     {    
1259       cstring sname;
1260       
1261       if (sRef_isPointer (s)) 
1262         {
1263           sRef base = sRef_getBase (s);
1264           sname = sRef_unparse (base);
1265         }
1266       else 
1267         {
1268           if (sRef_isAddress (s))
1269             {
1270               sRef p = sRef_constructPointer (s);
1271               sname = sRef_unparse (p);
1272             }
1273           else
1274             {
1275               sname = sRef_unparse (s);
1276             }
1277         }
1278       
1279       if (!sRef_isValid (alias) || sRef_sameName (s, alias))
1280         {
1281           if (sRef_isMeaningful (s))
1282             {
1283               if (optgenerror 
1284                   (FLG_MODOBSERVER,
1285                    message ("Suspect modification of observer %s: %s", 
1286                             sname, exprNode_unparse (err)), 
1287                    exprNode_isDefined (f) ? f->loc : g_currentloc))
1288                 {
1289                   sRef_showExpInfo (s);
1290                 }
1291             }
1292           else
1293             {
1294               voptgenerror 
1295                 (FLG_MODOBSERVER,
1296                  message ("Suspect modification of observer returned by "
1297                           "function call: %s", 
1298                           exprNode_unparse (err)), 
1299                  exprNode_isDefined (f) ? f->loc : g_currentloc);
1300             }
1301         }
1302       else
1303         {
1304           if (optgenerror
1305               (FLG_MODOBSERVER,
1306                message ("Suspect modification of observer %s through alias %q: %s", 
1307                         sname, sRef_unparse (alias), exprNode_unparse (err)), 
1308                exprNode_isDefined (f) ? f->loc : g_currentloc))
1309             {
1310               sRef_showExpInfo (s);
1311             }
1312         }
1313       
1314       cstring_free (sname);
1315     }
1316   
1317   (void) checkModifyAuxAux (s, f, alias, err);
1318   return FALSE;
1319 }
1320
1321 static
1322 bool checkModifyValAux (/*@exposed@*/ sRef s, exprNode f, sRef alias, exprNode err)
1323 {
1324   (void) checkModifyAuxAux (s, f, alias, err);
1325   return FALSE;
1326 }
1327
1328 static
1329 bool checkCallModifyAux (/*@exposed@*/ sRef s, exprNode f, sRef alias, exprNode err)
1330 {
1331   bool result = FALSE;
1332
1333   DPRINTF (("Check modify aux: %s / %s",
1334             sRef_unparse (s), sRef_unparse (alias)));
1335
1336   if (sRef_isObserver (s) && context_maybeSet (FLG_MODOBSERVER))
1337     {    
1338       sRef p = sRef_isAddress (s) ? sRef_constructPointer (s) : s;
1339       cstring sname = sRef_unparse (p);
1340
1341       if (!sRef_isValid (alias) || sRef_sameName (s, alias))
1342         {
1343           if (sRef_isMeaningful (s))
1344             {
1345               result = optgenerror 
1346                 (FLG_MODOBSERVER,
1347                  message ("Suspect modification of observer %s: %s", 
1348                           sname, exprNode_unparse (err)), 
1349                  exprNode_isDefined (f) ? f->loc : g_currentloc);
1350             }
1351           else
1352             {
1353               result = optgenerror 
1354                 (FLG_MODOBSERVER,
1355                  message ("Suspect modification of observer returned by "
1356                           "function call: %s", 
1357                           exprNode_unparse (err)), 
1358                  exprNode_isDefined (f) ? f->loc : g_currentloc);
1359             }
1360         }
1361       else
1362         {
1363           result = optgenerror 
1364             (FLG_MODOBSERVER,
1365              message
1366              ("Suspect modification of observer %s through alias %q: %s", 
1367               sname, sRef_unparse (alias), exprNode_unparse (err)), 
1368              exprNode_isDefined (f) ? f->loc : g_currentloc);
1369         }
1370       
1371       cstring_free (sname);
1372     }
1373   else if (context_maybeSet (FLG_MODIFIES))
1374     {
1375       DPRINTF (("can modify: %s / %s",
1376                 sRef_unparse (s),
1377                 sRefSet_unparse (context_modList ())));
1378
1379       if (!(sRef_canModifyVal (s, context_modList ())))
1380         {
1381           sRef p = sRef_isAddress (s) ? sRef_constructPointer (s) : s;
1382           cstring sname = sRef_unparse (p);
1383           bool hasMods = context_hasMods ();
1384           sRef rb = sRef_getRootBase (s);
1385           flagcode errCode = hasMods ? FLG_MODIFIES : FLG_MODNOMODS;
1386           bool check = TRUE;
1387
1388           DPRINTF (("Can't modify! %s", sRef_unparse (s)));
1389
1390           if (sRef_isFileOrGlobalScope (rb))
1391             {
1392               uentry ue = sRef_getUentry (rb);
1393               
1394               /* be more specific here! */
1395               if (!uentry_isCheckedModify (ue))
1396                 {
1397                   check = FALSE;
1398                 }
1399             }
1400           
1401           if (check)
1402             {
1403               if (!sRef_isValid (alias) || sRef_sameName (s, alias))
1404                 {
1405                   if (sRef_isLocalVar (sRef_getRootBase (s)))
1406                     {
1407                       voptgenerror 
1408                         (errCode,
1409                          message 
1410                          ("Undocumented modification of internal "
1411                           "state (%q) through call to %s: %s", 
1412                           sRef_unparse (s), exprNode_unparse (f),
1413                           exprNode_unparse (err)), 
1414                          exprNode_isDefined (f) ? f->loc : g_currentloc);
1415                     }
1416                   else
1417                     {
1418                       if (sRef_isSystemState (s))
1419                         {
1420                           if (errCode == FLG_MODNOMODS) 
1421                             {
1422                               if (context_getFlag (FLG_MODNOMODS))
1423                                 {
1424                                   errCode = FLG_MODFILESYSTEM;
1425                                 }
1426                             }
1427                           else
1428                             {
1429                               errCode = FLG_MODFILESYSTEM;
1430                             }
1431                         }
1432                       
1433                       result = optgenerror 
1434                         (errCode,
1435                          message ("Undocumented modification of %s "
1436                                   "possible from call to %s: %s", 
1437                                   sname,
1438                                   exprNode_unparse (f),
1439                                   exprNode_unparse (err)),
1440                          exprNode_isDefined (f) ? f->loc : g_currentloc);
1441                     }
1442                 }
1443               else
1444                 {
1445                   result = optgenerror
1446                     (errCode,
1447                      message ("Undocumented modification of %s possible "
1448                               "from call to %s (through alias %q): %s", 
1449                               sname,
1450                               exprNode_unparse (f), 
1451                               sRef_unparse (alias), 
1452                               exprNode_unparse (err)),
1453                      exprNode_isDefined (f) ? f->loc : g_currentloc);
1454                 }
1455             }
1456           cstring_free (sname);
1457         }
1458     }
1459   else
1460     {
1461       if (context_maybeSet (FLG_MUSTMOD))
1462         {
1463           (void) sRef_canModifyVal (s, context_modList ());
1464         }
1465     }
1466
1467   return result;
1468 }
1469
1470 void exprNode_checkCallModifyVal (sRef s, exprNodeList args, exprNode f, exprNode err)
1471 {
1472   s = sRef_fixBaseParam (s, args);
1473   DPRINTF (("Check call modify: %s", sRef_unparse (s)));
1474   sRef_aliasCheckPred (checkCallModifyAux, NULL, s, f, err);
1475 }
1476
1477 void
1478 exprChecks_checkExport (uentry e)
1479 {
1480   if (context_checkExport (e))
1481     {
1482       fileloc fl = uentry_whereDeclared (e);
1483       
1484       if (fileloc_isHeader (fl) && !fileloc_isLib (fl) 
1485           && !fileloc_isImport (fl) && !uentry_isStatic (e))
1486         {
1487           if (uentry_isFunction (e) || 
1488               (uentry_isVariable (e) && ctype_isFunction (uentry_getType (e))))
1489             {
1490               voptgenerror 
1491                 (FLG_EXPORTFCN,
1492                  message ("Function exported, but not specified: %q", 
1493                           uentry_getName (e)),
1494                  fl);
1495             }
1496           else if (uentry_isExpandedMacro (e))
1497             {
1498               voptgenerror
1499                 (FLG_EXPORTMACRO,
1500                  message ("Expanded macro exported, but not specified: %q", 
1501                           uentry_getName (e)),
1502                  fl);
1503             }
1504           else if (uentry_isVariable (e) && !uentry_isParam (e)) 
1505             {
1506               voptgenerror 
1507                 (FLG_EXPORTVAR,
1508                  message ("Variable exported, but not specified: %q", 
1509                           uentry_getName (e)),
1510                  fl);
1511             }
1512           else if (uentry_isEitherConstant (e))
1513             {
1514               voptgenerror 
1515                 (FLG_EXPORTCONST,
1516                  message ("Constant exported, but not specified: %q", 
1517                           uentry_getName (e)),
1518                  fl);
1519             }
1520           else if (uentry_isIter (e) || uentry_isEndIter (e))
1521             {
1522               voptgenerror 
1523                 (FLG_EXPORTITER,
1524                  message ("Iterator exported, but not specified: %q", 
1525                           uentry_getName (e)),
1526                  fl);
1527             }
1528
1529           else if (uentry_isDatatype (e))
1530             {
1531               ; /* error already reported */
1532             }
1533           else
1534             {
1535               BADEXIT;
1536             }
1537         }
1538     }
1539 }
1540
1541 static void checkSafeReturnExpr (/*@notnull@*/ exprNode e)
1542 {
1543   ctype tr = ctype_getReturnType (context_currentFunctionType ());
1544   ctype te = exprNode_getType (e);
1545
1546   /* evans 2001-08-21: added test to warn about void returns from void functions */
1547   if (ctype_isVoid (tr))
1548     {
1549       (void) gentypeerror
1550         (te, e, tr, exprNode_undefined,
1551          message ("Return expression from function declared void: %s", exprNode_unparse (e)),
1552          e->loc);
1553       return;
1554     }
1555
1556   if (!ctype_forceMatch (tr, te) && !exprNode_matchLiteral (tr, e))
1557     {
1558       (void) gentypeerror
1559         (te, e, tr, exprNode_undefined,
1560          message ("Return value type %t does not match declared type %t: %s",
1561                   te, tr, exprNode_unparse (e)),
1562          e->loc);
1563     }
1564   else
1565     {
1566       sRef ret = e->sref;
1567       uentry rval = context_getHeader ();
1568       sRef resultref = uentry_getSref (rval);
1569
1570       DPRINTF (("Check return: %s / %s / %s",
1571                 exprNode_unparse (e),
1572                 sRef_unparseFull (e->sref),
1573                 uentry_unparse (rval)));
1574
1575       transferChecks_return (e, rval);
1576
1577       DPRINTF (("After return: %s / %s / %s",
1578                 exprNode_unparse (e),
1579                 sRef_unparseFull (e->sref),
1580                 uentry_unparse (rval)));
1581
1582       if (!(sRef_isExposed (uentry_getSref (context_getHeader ()))
1583             || sRef_isObserver (uentry_getSref (context_getHeader ())))
1584           && (context_getFlag (FLG_RETALIAS) 
1585               || context_getFlag (FLG_RETEXPOSE)))
1586         {
1587           sRef base = sRef_getRootBase (ret);
1588           ctype rtype = e->typ;
1589
1590           if (ctype_isUnknown (rtype))
1591             {
1592               rtype = tr;
1593             }
1594
1595           if (ctype_isVisiblySharable (rtype))
1596             {
1597               if (context_getFlag (FLG_RETALIAS))
1598                 {
1599                   sRef_aliasCheckPred (checkRefGlobParam, NULL, base, 
1600                                        e, exprNode_undefined);
1601                 }
1602               
1603               if (context_getFlag (FLG_RETEXPOSE) && sRef_isIReference (ret) 
1604                   && !sRef_isExposed (resultref) && !sRef_isObserver (resultref))
1605                 {
1606                   sRef_aliasCheckPred (checkRepExposed, NULL, base, e, 
1607                                        exprNode_undefined);
1608                 }
1609             }
1610         }
1611     }
1612 }
1613
1614
1615
1616
1617
This page took 0.157023 seconds and 3 git commands to generate.