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 ** exprNode.c
26 */
27 
28 # include <ctype.h> /* for isdigit */
29 # include "splintMacros.nf"
30 # include "basic.h"
31 # include "cgrammar.h"
32 # include "cscanner.h"
33 # include "cscannerHelp.h"
34 # include "cgrammar_tokens.h"
35 
36 # include "exprChecks.h"
37 # include "transferChecks.h"
38 # include "exprNodeSList.h"
39 
40 static bool exprNode_sameStorage (exprNode p_e1, exprNode p_e2) /*@*/ ;
41 static bool exprNode_isEmptyStatement (exprNode p_e);
42 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
43 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
44 static bool exprNode_isStatement (exprNode p_e);
45 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
46 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
47 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
48 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
49 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
50 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
51 static void checkUniqueParams (exprNode p_fcn,
52 			       /*@notnull@*/ exprNode p_current, exprNodeList p_args,
53 			       int p_paramno, uentry p_ucurrent);
54 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
55 static bool abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
56 			     /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
57 			     fileloc p_loc1, fileloc p_loc2)
58    /*@modifies g_warningstream@*/ ;
59 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
60 			    /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
61 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
62 static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
63 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
64 static void checkMacroParen (exprNode p_e);
65 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
66 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
67 static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
68 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
69 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
70 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
71 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
72 			  /*@dependent@*/ cstring p_fname,
73 			  uentryList p_pn, exprNodeList p_args,
74 			  bool p_hasMods, sRefSet p_mods, bool p_isSpec,
75 			  int p_specialArgs);
76 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
77 			 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
78 static void
79   checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
80 
81 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
82   /*@globals internalState@*/ ;
83 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
84 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
85 static /*@exposed@*/ exprNode
86   exprNode_lastStatement (/*@returned@*/ exprNode p_e);
87 
88 static /*@only@*/ exprNode s_mustExitNode = exprNode_undefined;
89 
90 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
91 			  uentryList p_cl,
92 			  exprNodeList p_args, bool p_isIter, exprNode p_ret);
93 
94 static bool inEffect = FALSE;
95 static int nowalloc = 0;
96 static int totalloc = 0;
97 static int maxalloc = 0;
98 
99 static /*@only@*/ uentry regArg;
100 static /*@only@*/ uentry outArg;
101 static /*@only@*/ uentry outStringArg;
102 static /*@exposed@*/ sRef stdinRef;
103 static /*@exposed@*/ sRef stdoutRef;
104 static /*@only@*/ uentry csArg;
105 static /*@only@*/ uentry csOnlyArg;
106 static ctype cstringType;
107 static ctype ctypeType;
108 static ctype filelocType;
109 static bool initMod = FALSE;
110 
111 /*@function void exprNode_swap (sef exprNode, sef exprNode)@*/
112 /*@-macroassign@*/
113 # define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE)
114 /*@=macroassign@*/
115 
exprNode_defineConstraints(exprNode e)116 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
117    /*@defines e->requiresConstraints,  e->ensuresConstraints,
118               e->trueEnsuresConstraints,  e->falseEnsuresConstraints @*/
119 {
120   e->requiresConstraints = constraintList_makeNew ();
121   e->ensuresConstraints = constraintList_makeNew ();
122   e->trueEnsuresConstraints = constraintList_makeNew ();
123   e->falseEnsuresConstraints = constraintList_makeNew ();
124 }
125 
126 /*
127 ** must occur after library has been read
128 */
129 
exprNode_initMod(void)130 void exprNode_initMod (void)
131   /*@globals undef regArg, undef outArg, undef outStringArg,
132              undef csOnlyArg, undef csArg;
133    @*/
134 {
135   uentry ue;
136   idDecl tmp;
137 
138   initMod = TRUE;
139   cstringType = ctype_unknown;
140   ctypeType = ctype_unknown;
141   filelocType = ctype_unknown;
142 
143   if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
144     {
145       cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
146     }
147 
148   if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
149     {
150       ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
151     }
152 
153   if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
154     {
155       filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
156     }
157 
158   if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
159     {
160       ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
161     }
162   else /* define stdin */
163     {
164       ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
165 				ctype_unknown,
166 				fileloc_getBuiltin (),
167 				FALSE);
168       uentry_setHasNameError (ue);
169       ue = usymtab_supGlobalEntryReturn (ue);
170     }
171 
172   stdinRef = sRef_makePointer (uentry_getSref (ue));
173 
174   if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
175     {
176       ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
177     }
178   else
179     {
180       ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
181 				ctype_unknown,
182 				fileloc_getBuiltin (),
183 				FALSE);
184       uentry_setHasNameError (ue);
185       ue = usymtab_supGlobalEntryReturn (ue);
186     }
187 
188   stdoutRef = sRef_makePointer (uentry_getSref (ue));
189 
190   tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
191 
192   regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
193 
194   idDecl_setTyp (tmp,
195 		 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
196 				qual_createOut ()));
197 
198   outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
199 
200   idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
201 				     qual_createOut ()));
202 
203   outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
204 
205   idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
206 						    qual_createOnly ()),
207 				     qual_createNull ()));
208 
209   csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
210 
211   idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
212   csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
213 
214   idDecl_free (tmp);
215 }
216 
217 void
exprNode_destroyMod(void)218 exprNode_destroyMod (void)
219    /*@globals killed regArg, killed outArg, killed outStringArg,
220 	      killed s_mustExitNode, initMod @*/
221 {
222   if (initMod)
223     {
224       /* evans 2002-07-12: changed uentry_free to uentry_freeComplete */
225       uentry_freeComplete (regArg);
226       uentry_freeComplete (outArg);
227       uentry_freeComplete (outStringArg);
228 
229       exprNode_free (s_mustExitNode);
230       initMod = FALSE;
231       /*@-branchstate@*/
232     }
233   /*@=branchstate@*/
234 }
235 
exprNode_resetSref(exprNode e)236 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
237 {
238   e->sref = sRef_undefined;
239 }
240 
exprNode_fakeCopy(exprNode e)241 exprNode exprNode_fakeCopy (exprNode e)
242 {
243   /*@-temptrans@*/ /*@-retalias@*/
244   return e;
245   /*@=temptrans@*/ /*@=retalias@*/
246 }
247 
isFlagKey(char key)248 static bool isFlagKey (char key)
249 {
250   return (key == '-' || key == '+' || key == ' ' || key == '#');
251 }
252 
exprNode_combineControl(exprNode ret,exprNode ifclause,exprNode elseclause)253 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
254 				     /*@notnull@*/ exprNode ifclause,
255 				     /*@notnull@*/ exprNode elseclause)
256 {
257   ret->canBreak = ifclause->canBreak || elseclause->canBreak;
258 
259   ret->mustBreak =
260     (ifclause->mustBreak || exprNode_mustEscape (ifclause))
261       && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
262 
263   ret->exitCode = exitkind_combine (ifclause->exitCode,
264 				    elseclause->exitCode);
265 
266 }
267 
268 /*
269 ** For exprNode's returned by exprNode_effect.
270 */
271 
shallowKind(exprKind kind)272 static bool shallowKind (exprKind kind)
273 {
274   return (kind == XPR_STRINGLITERAL
275 	  || kind == XPR_NUMLIT
276 	  || kind == XPR_EMPTY
277 	  || kind == XPR_BODY
278 	  || kind == XPR_NODE);
279 }
280 
281 static void
exprNode_freeIniter(exprNode e)282 exprNode_freeIniter (/*@only@*/ exprNode e)
283 {
284   if (!exprNode_isError (e))
285     {
286       switch (e->kind)
287 	{
288 	case XPR_FACCESS:
289 	  /*
290 	  ** Its a fake copy, don't free the field->rec and field->field
291 	  ** fields.
292 	  */
293 
294 	  /*@-compdestroy@*/
295 	  sfree (e->edata->field);
296 	  /*@=compdestroy@*/
297 
298 	  sfree (e->edata);
299 	  break;
300 	case XPR_FETCH:
301 	  exprNode_free (e->edata->op->b);
302 	  /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
303 	  sfree (e->edata);
304 	  break;
305 	default:
306 	  llbug (message ("other: %s", exprNode_unparse (e)));
307 	}
308 
309       multiVal_free (e->val);
310       cstring_free (e->etext);
311       fileloc_free (e->loc);
312       sRefSet_free (e->uses);
313       sRefSet_free (e->sets);
314       sRefSet_free (e->msets);
315       guardSet_free (e->guards);
316 
317       constraintList_free(e->requiresConstraints);
318       constraintList_free(e->ensuresConstraints);
319       constraintList_free(e->trueEnsuresConstraints);
320       constraintList_free(e->falseEnsuresConstraints);
321 
322       e->requiresConstraints = NULL;
323       e->ensuresConstraints = NULL;
324       e->trueEnsuresConstraints = NULL;
325       e->falseEnsuresConstraints = NULL;
326 
327       sfree (e);
328     }
329 }
330 
331 void
exprNode_freeShallow(exprNode e)332 exprNode_freeShallow (/*@only@*/ exprNode e)
333 {
334   if (!exprNode_isError (e))
335     {
336       if (shallowKind (e->kind))
337 	{
338 	  	}
339       else
340 	{
341 	  if (!inEffect)
342 	    {
343 	      if (e->kind == XPR_EMPTY
344 		  || e->kind == XPR_BODY
345 		  || e->kind == XPR_STRINGLITERAL
346 		  || e->kind == XPR_NUMLIT
347 		  || e->kind == XPR_NODE
348 		  || e->kind == XPR_OFFSETOF
349 		  || e->kind == XPR_ALIGNOFT
350 		  || e->kind == XPR_ALIGNOF
351 		  || e->kind == XPR_SIZEOFT
352 		  || e->kind == XPR_SIZEOF)
353 		{
354 		  /* don't free anything */
355 		}
356 	      else
357 		{
358 		  /* multiVal_free (e->val);  */
359 		  cstring_free (e->etext);
360 		  fileloc_free (e->loc);
361 		  sRefSet_free (e->uses);
362 		  sRefSet_free (e->sets);
363 		  sRefSet_free (e->msets);
364 		  guardSet_free (e->guards);
365 		  exprData_freeShallow (e->edata, e->kind);
366 		  nowalloc--;
367 		  /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
368 		  /*@-branchstate@*/
369 		}
370 	    }
371 	} /*@=branchstate@*/
372     }
373   }
374 
375 void
exprNode_free(exprNode e)376 exprNode_free (exprNode e)
377 {
378   if (!exprNode_isError (e))
379     {
380       if (!inEffect)
381 	{
382 	  multiVal_free (e->val);
383 	  cstring_free (e->etext);
384 	  fileloc_free (e->loc);
385 	  sRefSet_free (e->uses);
386 	  sRefSet_free (e->sets);
387 	  sRefSet_free (e->msets);
388 	  guardSet_free (e->guards);
389 	  exprData_free (e->edata, e->kind);
390 
391 	  constraintList_free(e->requiresConstraints);
392 	  constraintList_free(e->ensuresConstraints);
393 	  constraintList_free(e->trueEnsuresConstraints);
394 	  constraintList_free(e->falseEnsuresConstraints);
395 
396 	  e->requiresConstraints = NULL;
397 	  e->ensuresConstraints = NULL;
398 	  e->trueEnsuresConstraints = NULL;
399 	  e->falseEnsuresConstraints = NULL;
400 
401 	  nowalloc--;
402 	  sfree (e);
403 	  /*@-branchstate@*/
404 	} /*@=branchstate@*/
405     }
406 }
407 
408 exprNode
exprNode_makeError()409 exprNode_makeError ()
410 {
411   return exprNode_undefined;
412 }
413 
414 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
exprNode_new(void)415 exprNode_new (void)
416 {
417   exprNode ret = (exprNode) dmalloc (sizeof (*ret));
418   /* static int lastexpnodes = 0; */
419 
420   nowalloc++;
421   totalloc++;
422 
423   if (nowalloc > maxalloc)
424     {
425       maxalloc = nowalloc;
426     }
427 
428   return ret;
429 }
430 
431 static /*@notnull@*/ /*@special@*/ exprNode
exprNode_createPlain(ctype c)432   exprNode_createPlain (ctype c)
433   /*@defines result@*/
434   /*@ensures isnull result->edata, result->loc, result->val, result->guards,
435                     result->uses, result->sets, result->msets, result->etext @*/
436   /*@*/
437 {
438   exprNode e = exprNode_new ();
439 
440   e->typ = c;
441   e->kind = XPR_EMPTY;
442   e->val = multiVal_undefined;
443   e->sref = sRef_undefined;
444   e->etext = cstring_undefined;
445   e->loc = fileloc_undefined;
446   e->guards = guardSet_undefined;
447   e->uses = sRefSet_undefined;
448   e->sets = sRefSet_undefined;
449   e->msets = sRefSet_undefined;
450   e->edata = exprData_undefined;
451   e->exitCode = XK_NEVERESCAPE;
452   e->canBreak = FALSE;
453   e->mustBreak = FALSE;
454   e->isJumpPoint = FALSE;
455 
456   exprNode_defineConstraints(e);
457 
458   return (e);
459 }
460 
exprNode_makeMustExit(void)461 /*@observer@*/ exprNode exprNode_makeMustExit (void)
462 {
463   if (exprNode_isUndefined (s_mustExitNode))
464     {
465       s_mustExitNode = exprNode_createPlain (ctype_unknown);
466       s_mustExitNode->exitCode = XK_MUSTEXIT;
467     }
468 
469   return s_mustExitNode;
470 }
471 
472 
exprNode_create(ctype c)473 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
474   /*@defines result@*/
475   /*@post:isnull result->edata, result->guards, result->val,
476                  result->uses, result->sets, result->msets@*/
477   /*@*/
478 {
479   exprNode e = exprNode_createPlain (c);
480   e->loc = fileloc_copy (g_currentloc);
481   return (e);
482 }
483 
exprNode_createUnknown(void)484 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
485   /*@defines result@*/
486   /*@post:isnull result->edata, result->guards,
487                  result->uses, result->sets, result->msets@*/
488   /*@*/
489 {
490   return (exprNode_create (ctype_unknown));
491 }
492 
493 static /*@notnull@*/ /*@special@*/ exprNode
exprNode_createLoc(ctype c,fileloc loc)494   exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
495   /*@defines result@*/
496   /*@post:isnull result->edata, result->guards, result->val,
497                  result->uses, result->sets, result->msets@*/
498   /*@*/
499 {
500   exprNode e = exprNode_createPlain (c);
501   e->loc = loc;
502   return (e);
503 }
504 
505 static void
exprNode_copySets(exprNode ret,exprNode e)506   exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
507   /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
508 {
509   if (exprNode_isDefined (e))
510     {
511       ret->guards = guardSet_copy (e->guards);
512       ret->uses = sRefSet_newCopy (e->uses);
513       ret->sets = sRefSet_newCopy (e->sets);
514       ret->msets = sRefSet_newCopy (e->msets);
515     }
516   else
517     {
518       ret->guards = guardSet_undefined;
519       ret->uses = sRefSet_undefined;
520       ret->sets = sRefSet_undefined;
521       ret->msets = sRefSet_undefined;
522     }
523 }
524 
525 static /*@notnull@*/ /*@special@*/ exprNode
exprNode_createPartialLocCopy(exprNode e,fileloc loc)526   exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
527   /*@defines result@*/
528   /*@post:isnull result->edata, result->etext@*/
529   /*@*/
530 {
531   exprNode ret = exprNode_new ();
532 
533   if (exprNode_isError (e))
534     {
535       ret->typ = ctype_unknown;
536       ret->val = multiVal_undefined;
537       ret->loc = loc;
538       ret->guards = guardSet_undefined;
539       ret->uses = sRefSet_undefined;
540       ret->sets = sRefSet_undefined;
541       ret->msets = sRefSet_undefined;
542     }
543   else
544     {
545       ret->typ = e->typ;
546       ret->val = multiVal_copy (e->val);
547       ret->loc = loc;
548       ret->guards = guardSet_copy (e->guards);
549       ret->uses = sRefSet_newCopy (e->uses);
550       ret->sets = sRefSet_newCopy (e->sets);
551       ret->msets = sRefSet_newCopy (e->msets);
552     }
553 
554   ret->kind = XPR_EMPTY;
555   ret->sref = sRef_undefined;
556   ret->etext = cstring_undefined;
557   ret->exitCode = XK_NEVERESCAPE;
558   ret->canBreak = FALSE;
559   ret->mustBreak = FALSE;
560   ret->isJumpPoint = FALSE;
561   ret->edata = exprData_undefined;
562 
563   exprNode_defineConstraints(ret);
564 
565   return (ret);
566 }
567 
568 
569 static /*@notnull@*/ /*@special@*/ exprNode
exprNode_createPartialCopy(exprNode e)570   exprNode_createPartialCopy (exprNode e)
571   /*@defines result@*/
572   /*@post:isnull result->edata, result->etext@*/
573   /*@*/
574 {
575   return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
576 }
577 
578 static /*@notnull@*/ /*@special@*/ exprNode
exprNode_createPartialNVCopy(exprNode e)579   exprNode_createPartialNVCopy (exprNode e)
580   /*@defines result@*/
581   /*@post:isnull result->edata, result->etext, result->val @*/
582   /*@*/
583 {
584   exprNode ret = exprNode_new ();
585 
586   if (exprNode_isError (e))
587     {
588       ret->typ = ctype_unknown;
589       ret->loc = fileloc_undefined;
590       ret->guards = guardSet_undefined;
591       ret->uses = sRefSet_undefined;
592       ret->sets = sRefSet_undefined;
593       ret->msets = sRefSet_undefined;
594     }
595   else
596     {
597       ret->typ = e->typ;
598       ret->loc = fileloc_copy (e->loc);
599       ret->guards = guardSet_copy (e->guards);
600       ret->uses = sRefSet_newCopy (e->uses);
601       ret->sets = sRefSet_newCopy (e->sets);
602       ret->msets = sRefSet_newCopy (e->msets);
603     }
604 
605   ret->val = multiVal_undefined;
606   ret->kind = XPR_EMPTY;
607   ret->sref = sRef_undefined;
608   ret->etext = cstring_undefined;
609   ret->exitCode = XK_NEVERESCAPE;
610   ret->canBreak = FALSE;
611   ret->mustBreak = FALSE;
612   ret->isJumpPoint = FALSE;
613   ret->edata = exprData_undefined;
614 
615   exprNode_defineConstraints(ret);
616 
617   return (ret);
618 }
619 
620 static /*@notnull@*/ /*@special@*/ exprNode
exprNode_createSemiCopy(exprNode e)621   exprNode_createSemiCopy (exprNode e)
622   /*@defines result@*/
623   /*@post:isnull result->edata, result->etext, result->sets,
624                  result->msets, result->uses, result->guards@*/
625   /*@*/
626 {
627   if (exprNode_isError (e))
628     {
629       return exprNode_createPlain (ctype_unknown);
630     }
631   else
632     {
633       exprNode ret = exprNode_new ();
634 
635       ret->typ = e->typ;
636       ret->val = multiVal_copy (e->val);
637       ret->loc = fileloc_copy (e->loc);
638       ret->guards = guardSet_undefined;
639       ret->uses = sRefSet_undefined;
640       ret->sets = sRefSet_undefined;
641       ret->msets = sRefSet_undefined;
642 
643       ret->kind = XPR_EMPTY;
644       ret->sref = sRef_undefined;
645       ret->etext = cstring_undefined;
646       ret->exitCode = XK_NEVERESCAPE;
647       ret->canBreak = FALSE;
648       ret->mustBreak = FALSE;
649       ret->isJumpPoint = FALSE;
650       ret->edata = exprData_undefined;
651 
652       exprNode_defineConstraints(ret);
653 
654       return (ret);
655     }
656 }
657 
658 bool
exprNode_isNullValue(exprNode e)659 exprNode_isNullValue (exprNode e)
660 {
661   if (exprNode_isDefined (e))
662     {
663       multiVal m = exprNode_getValue (e);
664 
665       if (multiVal_isInt (m))
666 	{
667 	  return (multiVal_forceInt (m) == 0);
668 	}
669     }
670 
671   return FALSE;
672 }
673 
674 static bool
exprNode_isUnknownConstant(exprNode e)675 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
676 {
677   while (e->kind == XPR_PARENS)
678     {
679       e = exprData_getUopNode (e->edata);
680 
681       if (!exprNode_isDefined (e))
682 	{
683 	  return FALSE;
684 	}
685 
686       /* evans 2002-02-05: was llassert (exprNode_isDefined (e)); but this can fail */
687     }
688 
689   if (e->kind == XPR_CONST)
690     {
691       multiVal m = exprNode_getValue (e);
692 
693       if (multiVal_isUnknown (m))
694 	{
695 	  return TRUE;
696 	}
697     }
698 
699   return FALSE;
700 }
701 
702 /*@only@*/ exprNode
exprNode_numLiteral(ctype c,cstring t,fileloc loc,long val)703   exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
704 		       /*@only@*/ fileloc loc, long val)
705 {
706   exprNode e = exprNode_createLoc (c, loc);
707 
708   e->kind = XPR_NUMLIT;
709 
710   llassert (multiVal_isUndefined (e->val));
711   e->val = multiVal_makeInt (val);
712   e->edata = exprData_makeLiteral (cstring_copy (t));
713 
714   if (val == 0)
715     {
716       e->sref = sRef_makeUnknown ();
717       sRef_setDefNull (e->sref, e->loc);
718     }
719 
720   DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
721   return (e);
722 }
723 
724 /*@only@*/ exprNode
exprNode_charLiteral(char c,cstring text,fileloc loc)725 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
726 {
727   exprNode e = exprNode_createLoc (ctype_char, loc);
728 
729   if (context_getFlag (FLG_CHARINTLITERAL))
730     {
731       e->typ = ctype_makeConj (ctype_char, ctype_int);
732     }
733 
734   e->kind = XPR_NUMLIT;
735   e->val = multiVal_makeChar (c);
736 
737   e->edata = exprData_makeLiteral (cstring_copy (text));
738   return (e);
739 }
740 
741 /*@only@*/ exprNode
exprNode_floatLiteral(double d,ctype ct,cstring text,fileloc loc)742 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
743 {
744   exprNode e = exprNode_createLoc (ct, loc);
745 
746   e->kind = XPR_NUMLIT;
747     e->val = multiVal_makeDouble (d);
748   e->edata = exprData_makeLiteral (cstring_copy (text));
749   return (e);
750 }
751 
exprNode_getValue(exprNode e)752 multiVal exprNode_getValue (exprNode e)
753 {
754   while (exprNode_isInParens (e)) {
755     if (e->edata != NULL) {
756       e = exprData_getUopNode (e->edata);
757     } else {
758       break;
759     }
760   }
761 
762   if (exprNode_isDefined (e)) {
763     return e->val;
764   } else {
765     return multiVal_undefined;
766   }
767 }
768 
769 /*@only@*/ exprNode
exprNode_combineLiterals(exprNode e,exprNode rest)770 exprNode_combineLiterals (exprNode e, exprNode rest)
771 {
772   cstring ns;
773 
774   /* Both must be string literals. */
775 
776   if (exprNode_isUndefined (rest) || exprNode_isUndefined (e))
777     {
778       exprNode_free (rest);
779       return e;
780     }
781 
782   if (!exprNode_isStringLiteral (e))
783     {
784       voptgenerror
785 	(FLG_SYNTAX,
786 	 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e),
787 		  exprNode_unparse (rest)),
788 	 e->loc);
789       exprNode_free (rest);
790       return e;
791     }
792 
793   if (!exprNode_isStringLiteral (rest))
794     {
795       voptgenerror
796 	(FLG_SYNTAX,
797 	 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e), exprNode_unparse (rest)),
798 	 rest->loc);
799 
800       exprNode_free (rest);
801       return e;
802     }
803 
804   ns = cstring_concat (multiVal_forceString (exprNode_getValue (e)),
805 		       multiVal_forceString (exprNode_getValue (rest)));
806 
807   multiVal_free (e->val);
808   exprData_free (e->edata, e->kind);
809   e->edata = exprData_makeLiteral (cstring_copy (ns));
810   e->val = multiVal_makeString (ns);
811   exprNode_free (rest);
812   return e;
813 }
814 
815 /*@only@*/ exprNode
exprNode_rawStringLiteral(cstring t,fileloc loc)816 exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
817 {
818   exprNode e = exprNode_createLoc (ctype_string, loc);
819   size_t len = cstring_length (t);
820 
821   if (context_getFlag (FLG_STRINGLITERALLEN))
822     {
823       if (len > size_fromInt (context_getValue (FLG_STRINGLITERALLEN)))
824 	{
825 	  voptgenerror (FLG_STRINGLITERALLEN,
826 			message
827 			("String literal length (%d) exceeds maximum "
828 			 "length (%d): \"%s\"",
829 			 size_toInt (len),
830 			 context_getValue (FLG_STRINGLITERALLEN),
831 			 t),
832 			e->loc);
833 	}
834     }
835 
836   e->kind = XPR_STRINGLITERAL;
837   e->val = multiVal_makeString (cstring_copy (t));
838   e->edata = exprData_makeLiteral (t);
839   e->sref = sRef_makeConst (ctype_string);
840 
841   if (context_getFlag (FLG_READONLYSTRINGS))
842     {
843       sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
844       sRef_setExKind (e->sref, XO_OBSERVER, loc);
845     }
846   else
847     {
848       sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
849     }
850 
851   return (e); /* s released */
852 }
853 
854 /*@only@*/ exprNode
exprNode_wideStringLiteral(cstring t,fileloc loc)855 exprNode_wideStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
856 {
857   exprNode res = exprNode_stringLiteral (t, loc);
858   res->typ = ctype_makeWideString ();
859   return res;
860 }
861 
862 /*@only@*/ exprNode
exprNode_stringLiteral(cstring t,fileloc loc)863 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
864 {
865   size_t len = size_fromInt (size_toInt (cstring_length (t)) - 2);
866   char *ts = cstring_toCharsSafe (t);
867   char *s = cstring_toCharsSafe (cstring_create (len + 1));
868 
869   llassert (*ts == '\"' && *(ts + len + 1) == '\"');
870   strncpy (s, ts+1, len);
871   *(s + len) = '\0';
872   cstring_free (t);
873   return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
874 }
875 
exprNode_fromUIO(cstring c)876 exprNode exprNode_fromUIO (cstring c)
877 {
878   fileloc loc = context_getSaveLocation ();
879   exprNode e  = exprNode_createPlain (ctype_unknown);
880 
881   e->kind = XPR_VAR;
882 
883   if (fileloc_isUndefined (loc))
884     {
885       loc = fileloc_copy (g_currentloc);
886     }
887 
888   e->loc = loc; /* save loc was mangled */
889   e->sref = sRef_undefined;
890 
891   if (usymtab_exists (c))
892     {
893       uentry ue = usymtab_lookupEither (c);
894 
895       if (uentry_isDatatype (ue)
896 	  && uentry_isSpecified (ue))
897 	{
898 	  llfatalerror
899 	    (message ("%q: Specified datatype %s used in code, but not defined. "
900 		      "(Cannot continue reasonably from this error.)",
901 		      fileloc_unparse (e->loc), c));
902 	}
903       else
904 	{
905 	  BADBRANCH;
906 	}
907     }
908 
909   llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
910 
911   /*
912   ** was supercedeGlobalEntry...is this better?
913   */
914 
915   if (!context_inIterEnd ())
916     {
917       if (context_inMacro ())
918         {
919 	  if (context_getFlag (FLG_UNRECOG))
920 	    {
921 	      voptgenerror
922 		(FLG_MACROUNDEF,
923 		 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
924 	    }
925 	  else
926 	    {
927 	      flagcode_recordSuppressed (FLG_UNRECOG);
928 	    }
929         }
930       else
931         {
932           voptgenerror
933 	    (FLG_UNRECOG, message ("Unrecognized identifier: %s", c),  e->loc);
934 	}
935     }
936 
937   e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
938 
939   /* No alias errors for unrecognized identifiers */
940   sRef_setAliasKind (e->sref, AK_ERROR, loc);
941 
942   return (e);
943 }
944 
exprNode_makeConstantString(cstring c,fileloc loc)945 exprNode exprNode_makeConstantString (cstring c, /*@only@*/ fileloc loc)
946 {
947   exprNode e  = exprNode_createPlain (ctype_unknown);
948   e->kind = XPR_VAR;
949   e->loc = loc;
950   e->sref = sRef_makeConst (ctype_string);
951   e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
952   e->typ = ctype_string;
953 
954   /* No alias errors for unrecognized identifiers */
955   sRef_setAliasKind (e->sref, AK_STATIC, loc);
956   sRef_setExKind (e->sref, XO_OBSERVER, loc);
957 
958   return (e);
959 }
960 
exprNode_createId(uentry c)961 exprNode exprNode_createId (/*@observer@*/ uentry c)
962 {
963   if (uentry_isValid (c))
964     {
965       exprNode e = exprNode_new ();
966 
967       DPRINTF (("create id: %s", uentry_unparse (c)));
968 
969       e->typ = uentry_getType (c);
970 
971       if (uentry_isFunction (c)
972 	  && !sRef_isLocalVar (uentry_getSref (c)))
973 	{
974 	  e->sref = sRef_undefined;
975 	}
976       else
977 	{
978 	  e->sref = uentry_getSref (c);
979 	}
980 
981       if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
982 	{
983 	  sRef_setDefined (e->sref, fileloc_undefined);
984 	}
985 
986       /*
987       ** yoikes!  leaving this out was a heinous bug...that would have been
988       ** caught if i had splint working first.  gag!
989       */
990 
991       e->etext = cstring_undefined;
992 
993       if (uentry_isEitherConstant (c))
994 	{
995 	  e->kind = XPR_CONST;
996 	  e->val = multiVal_copy (uentry_getConstantValue (c));
997 	}
998       else
999 	{
1000 	  e->kind = XPR_VAR;
1001 	  e->val = multiVal_unknown ();
1002 	}
1003 
1004       e->edata = exprData_makeId (c);
1005       e->loc = context_getSaveLocation ();
1006 
1007       if (fileloc_isUndefined (e->loc))
1008 	{
1009 	  fileloc_free (e->loc);
1010 	  e->loc = fileloc_copy (g_currentloc);
1011 	}
1012 
1013       e->guards = guardSet_new ();
1014 
1015       e->sets = sRefSet_new ();
1016       e->msets = sRefSet_new ();
1017       e->uses = sRefSet_new ();
1018 
1019       /*> missing fields, detected by splint <*/
1020       e->exitCode = XK_NEVERESCAPE;
1021       e->isJumpPoint = FALSE;
1022       e->canBreak = FALSE;
1023       e->mustBreak = FALSE;
1024 
1025       exprNode_defineConstraints (e);
1026       return e;
1027     }
1028   else
1029     {
1030       return exprNode_createUnknown ();
1031     }
1032 }
1033 
1034 /*@notnull@*/ exprNode
exprNode_fromIdentifier(uentry c)1035 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1036 {
1037   exprNode ret;
1038 
1039   if (context_justPopped ()) /* watch out! c could be dead */
1040     {
1041       uentry ce = usymtab_lookupSafe (cscannerHelp_observeLastIdentifier ());
1042 
1043       if (uentry_isValid (ce))
1044         {
1045           c = ce;
1046         }
1047       else
1048 	{
1049 	  llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1050 	}
1051     }
1052 
1053   ret = exprNode_fromIdentifierAux (c);
1054   return ret;
1055 }
1056 
exprNode_checkStringLiteralLength(ctype t1,exprNode e2)1057 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1058 {
1059   multiVal mval = exprNode_getValue (e2);
1060   cstring slit;
1061   size_t len;
1062 
1063   if (ctype_isFixedArray (t1))
1064     {
1065       size_t nelements = ctype_getArraySize (t1);
1066 
1067       llassert (multiVal_isString (mval));
1068       slit = multiVal_forceString (mval);
1069 
1070       len = cstring_lengthExpandEscapes (slit);
1071 
1072       llassert (exprNode_isDefined (e2));
1073 
1074       if (len == nelements)
1075 	{
1076 	  mstring temp;
1077 
1078 	  temp = cstring_expandEscapes (slit);
1079 
1080 	  if (temp[len-1] == '\0')
1081 	    {
1082 	      voptgenerror
1083 		(FLG_STRINGLITNOROOMFINALNULL,
1084 		 message ("String literal with %d character%& "
1085 			  "is assigned to %s (no room for final null terminator): %s",
1086 			  size_toInt (len + 1),
1087 			  ctype_unparse (t1),
1088 			  exprNode_unparse (e2)),
1089 		 e2->loc);
1090 	    }
1091 	  else
1092 	    {
1093 	      voptgenerror
1094 		(FLG_STRINGLITNOROOM,
1095 		 message ("String literal with %d character%& "
1096 			  "is assigned to %s (no room for null terminator): %s",
1097 			  size_toInt (len + 1),
1098 			  ctype_unparse (t1),
1099 			  exprNode_unparse (e2)),
1100 		 e2->loc);
1101 	    }
1102 	}
1103       else if (len > nelements)
1104 	{
1105 	  voptgenerror
1106 	    (FLG_STRINGLITTOOLONG,
1107 	     message ("String literal with %d character%& (counting null terminator) "
1108 		      "is assigned to %s (insufficient storage available): %s",
1109 		      size_toInt (len + 1),
1110 		      ctype_unparse (t1),
1111 		      exprNode_unparse (e2)),
1112 	     e2->loc);
1113 	}
1114       else if (len < nelements - 1)
1115 	{
1116 	  voptgenerror
1117 	    (FLG_STRINGLITSMALLER,
1118 	     message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1119 		      size_toInt (len + 1),
1120 		      ctype_unparse (t1),
1121 		      exprNode_unparse (e2)),
1122 	     e2->loc);
1123 	}
1124       else
1125 	{
1126 	  ; /* okay */
1127 	}
1128     }
1129 }
1130 
1131 static /*@only@*/ /*@notnull@*/ exprNode
exprNode_fromIdentifierAux(uentry c)1132 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1133 {
1134   exprNode e = exprNode_createId (c);
1135   sRef sr = e->sref;
1136 
1137   uentry_setUsed (c, e->loc);
1138 
1139   if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1140     {
1141       checkGlobUse (c, FALSE, e);
1142     }
1143 
1144   return (e);
1145 }
1146 
1147 static bool
exprNode_isZero(exprNode e)1148 exprNode_isZero (exprNode e)
1149 {
1150   if (exprNode_isDefined (e))
1151     {
1152       multiVal m = exprNode_getValue (e);
1153 
1154       if (multiVal_isInt (m))
1155 	{
1156 	  return (multiVal_forceInt (m) == 0);
1157 	}
1158     }
1159 
1160   return FALSE;
1161 }
1162 
1163 static bool
exprNode_isNonNegative(exprNode e)1164 exprNode_isNonNegative (exprNode e)
1165 {
1166   if (exprNode_isDefined (e))
1167     {
1168       multiVal m = exprNode_getValue (e);
1169 
1170       if (multiVal_isInt (m))
1171 	{
1172 	  return (multiVal_forceInt (m) >= 0);
1173 	}
1174 
1175       /*
1176       ** This is not always true if programmer defines enum
1177       ** values, but then the constant should be known.
1178       */
1179 
1180       if (ctype_isEnum (ctype_realType (e->typ)))
1181 	{
1182 	  return TRUE;
1183 	}
1184     }
1185 
1186   return FALSE;
1187 }
1188 
1189 /*
1190 ** a[x]  - uses a but NOT a[]
1191 **         result sref = a[]  (set/use in assignment)
1192 **
1193 ** The syntax x[a] is also legal in C, and has the same
1194 ** semantics.  If ind is an array, and arr is an int, flip
1195 ** the arguments.
1196 */
1197 
1198 /*@only@*/ exprNode
exprNode_arrayFetch(exprNode e1,exprNode e2)1199 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1200 {
1201   /*
1202   ** error in arr, error propagates (no new messages)
1203   ** error in ind, assume valid and continue
1204   */
1205 
1206   DPRINTF (("Array fetch: %s / %s",
1207 	    exprNode_unparse (e1), exprNode_unparse (e2)));
1208 
1209   if (exprNode_isError (e1))
1210     {
1211       exprNode_free (e2);
1212       return (exprNode_makeError ());
1213     }
1214   else
1215     {
1216       exprNode arr;
1217       exprNode ind;
1218       ctype carr = exprNode_getType (e1);
1219       ctype crarr = ctype_realType (carr);
1220 
1221       /*
1222       ** this sets up funny aliasing, that leads to spurious
1223       ** splint errors.  Hence, the i2 comments.
1224       */
1225 
1226       /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1227       if (ctype_isKnown (crarr)
1228 	  && !ctype_isRealArray (crarr)
1229 	  && ctype_isRealNumeric (crarr)
1230 	  && !exprNode_isError (e2)
1231 	  && ctype_isRealAP (exprNode_getType (e2)))  /* fetch like 3[a] */
1232 	{
1233 	  arr = e2;
1234 	  ind = e1;
1235 
1236 	  carr = exprNode_getType (arr);
1237 	  crarr = ctype_realType (carr);
1238 	}
1239       else
1240 	{
1241 	  arr = e1;
1242 	  ind = e2;
1243 	}
1244 
1245       DPRINTF (("arr: %s", exprNode_unparse (arr)));
1246 
1247       if (sRef_possiblyNull (arr->sref))
1248         {
1249           if (!usymtab_isGuarded (arr->sref))
1250             {
1251 	      if (!context_inSizeof() )
1252 		{
1253 		  if (optgenerror (FLG_NULLDEREF,
1254 				   message ("Index of %s pointer %q: %s",
1255 					    sRef_nullMessage (arr->sref),
1256 					    sRef_unparse (arr->sref),
1257 					    exprNode_unparse (arr)),
1258 				   arr->loc))
1259 		    {
1260 		      DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1261 		      sRef_showNullInfo (arr->sref);
1262 
1263 		      /* suppress future messages */
1264 		      sRef_setNullError (arr->sref);
1265 		    }
1266 		}
1267             }
1268         }
1269 
1270       if (exprNode_isError (ind))
1271         {
1272           if ((ctype_isArrayPtr (crarr)
1273 	       && !ctype_isFunction (crarr))
1274 	      || ctype_isUnknown (carr))
1275             {
1276               exprNode ret = exprNode_createPartialCopy (arr);
1277 
1278               if (ctype_isKnown (carr))
1279 		{
1280 		  ret->typ = ctype_baseArrayPtr (crarr);
1281 		}
1282               else
1283 		{
1284 		  ret->typ = ctype_unknown;
1285 		}
1286 
1287               ret->sref = sRef_makeArrayFetch (arr->sref);
1288 
1289               ret->kind = XPR_FETCH;
1290 
1291 	      /*
1292               ** Because of funny aliasing (when arr and ind are
1293 	      ** flipped) spurious errors would be reported here.
1294 	      */
1295 
1296               /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1297               checkSafeUse (ret, arr->sref);
1298               return (ret);
1299             }
1300           else
1301             {
1302               voptgenerror (FLG_TYPE,
1303 			    message ("Array fetch from non-array (%t): %s[%s]", carr,
1304 				     exprNode_unparse (e1), exprNode_unparse (e2)),
1305 			    arr->loc);
1306               exprNode_free (arr);
1307               return (exprNode_makeError ());
1308             }
1309         }
1310       else
1311         {
1312           if (!ctype_isForceRealInt (&(ind->typ)))
1313             {
1314 	      ctype rt = ctype_realType (ind->typ);
1315 
1316               if (ctype_isChar (rt))
1317 		{
1318 		  vnoptgenerror
1319 		    (FLG_CHARINDEX,
1320 		     message ("Array fetch using non-integer, %t: %s[%s]",
1321 			      ind->typ,
1322 			      exprNode_unparse (e1), exprNode_unparse (e2)),
1323 		     arr->loc);
1324 		}
1325 	      else if (ctype_isEnum (rt))
1326 		{
1327 		  vnoptgenerror
1328 		    (FLG_ENUMINDEX,
1329 		     message ("Array fetch using non-integer, %t: %s[%s]",
1330 			      ind->typ,
1331 			      exprNode_unparse (e1), exprNode_unparse (e2)),
1332 		     arr->loc);
1333 		}
1334               else if (ctype_isNumAbstract (rt))
1335 		{
1336 		  vnoptgenerror
1337 		    (FLG_NUMABSTRACTINDEX,
1338 		     message ("Array fetch using numabstract type, %t: %s[%s]",
1339 			      ind->typ,
1340 			      exprNode_unparse (e1), exprNode_unparse (e2)),
1341 		     arr->loc);
1342 		}
1343               else
1344 		{
1345 		  voptgenerror
1346 		    (FLG_TYPE,
1347 		     message ("Array fetch using non-integer, %t: %s[%s]",
1348 			      ind->typ,
1349 			      exprNode_unparse (e1), exprNode_unparse (e2)),
1350 		     arr->loc);
1351 		}
1352 
1353 	      multiVal_free (ind->val);
1354               ind->val = multiVal_unknown ();
1355             }
1356 
1357           if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1358             {
1359               exprNode ret = exprNode_createSemiCopy (arr);
1360               multiVal m = exprNode_getValue (ind);
1361 
1362               ret->typ = ctype_baseArrayPtr (crarr);
1363               ret->kind = XPR_FETCH;
1364 
1365               if (multiVal_isInt (m))
1366 		{
1367 		  int i = (int) multiVal_forceInt (m);
1368 
1369 		  if (sRef_isValid (arr->sref)) {
1370 		    ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1371 		  } else {
1372 		    ret->sref = sRef_undefined;
1373 		  }
1374 		}
1375               else
1376 		{
1377 		  ret->sref = sRef_makeArrayFetch (arr->sref);
1378 		}
1379 
1380               ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1381               ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1382               ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1383 
1384 	      /* (see comment on spurious errors above) */
1385               /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1386 
1387               exprNode_checkUse (ret, ind->sref, ind->loc);
1388               exprNode_checkUse (ret, arr->sref, arr->loc);
1389 
1390               return (ret);
1391             }
1392           else
1393             {
1394               if (ctype_isUnknown (carr))
1395 		{
1396 		  exprNode ret = exprNode_createPartialCopy (arr);
1397 
1398 		  ret->kind = XPR_FETCH;
1399 		  ret->typ = ctype_unknown;
1400 		  ret->sets = sRefSet_union (ret->sets, ind->sets);
1401 		  ret->msets = sRefSet_union (ret->msets, ind->msets);
1402 		  ret->uses = sRefSet_union (ret->uses, ind->uses);
1403 
1404 		  /* (see comment on spurious errors above) */
1405 		  /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1406 
1407 		  exprNode_checkUse (ret, ind->sref, ind->loc);
1408 		  exprNode_checkUse (ret, arr->sref, arr->loc);
1409 		  return (ret);
1410 		}
1411               else
1412 		{
1413 		  voptgenerror
1414 		    (FLG_TYPE,
1415 		     message ("Array fetch from non-array (%t): %s[%s]", carr,
1416 			      exprNode_unparse (e1), exprNode_unparse (e2)),
1417 		     arr->loc);
1418 
1419 		  exprNode_free (arr);
1420 		  exprNode_free (ind);
1421 
1422 		  return (exprNode_makeError ());
1423 		}
1424             }
1425         }
1426     }
1427   BADEXIT;
1428 }
1429 
1430 
1431 static int
checkArgs(uentry fcn,exprNode f,ctype t,exprNodeList args,exprNode ret)1432 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1433 	   exprNodeList args, exprNode ret)
1434 {
1435   return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1436 }
1437 
1438 /*
1439 ** checkPrintfArgs --- checks arguments for printf-like functions
1440 **    Arguments before ... have already been checked.
1441 **    The argument before the ... is a char *.
1442 **    argno is the format string argument.
1443 */
1444 
1445 static void
checkPrintfArgs(exprNode f,uentry fcn,exprNodeList args,exprNode ret,int argno)1446 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1447 		 exprNodeList args, exprNode ret, int argno)
1448 {
1449   /*
1450   ** the last argument before the elips is the format string
1451   */
1452 
1453   int i = argno;
1454   fileloc formatloc;
1455   int nargs = exprNodeList_size (args);
1456   uentryList params = uentry_getParams (fcn);
1457   exprNode a;
1458 
1459   /*
1460   ** These should be ensured by checkSpecialFunction
1461   */
1462 
1463   llassert (uentryList_size (params) == argno + 1);
1464   llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1465 
1466   a = exprNodeList_getN (args, argno - 1);
1467   formatloc = fileloc_copy (exprNode_loc (a));
1468 
1469   if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1470       && exprNode_knownStringValue (a))
1471     {
1472       char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1473       char *code = format;
1474       char *ocode = code;
1475 
1476       nargs = exprNodeList_size (args);
1477 
1478       while ((code = strchr (code, '%')) != NULL)
1479         {
1480           char *origcode = code;
1481 	  cstring codetext = cstring_newEmpty ();
1482           char key = *(++code);
1483           ctype modtype = ctype_int;
1484           bool modified = FALSE;
1485 
1486 	  fileloc_addColumn (formatloc, code - ocode);
1487 
1488 	  codetext = cstring_appendChar (codetext, key);
1489 
1490 	  /* ignore flags */
1491 	  while (isFlagKey (key))
1492 	    {
1493 	      key = *(++code);
1494 	      codetext = cstring_appendChar (codetext, key);
1495 	      fileloc_incColumn (formatloc);
1496 	    }
1497 
1498 	  if (key == 'm') /* skipped in syslog */
1499 	    {
1500 	      continue;
1501 	    }
1502 
1503 	  /* ignore field width */
1504 	  while (isdigit ((int) key) != 0)
1505 	    {
1506 	      key = *(++code);
1507 	      codetext = cstring_appendChar (codetext, key);
1508 	      fileloc_incColumn (formatloc);
1509 	    }
1510 
1511 	  /* ignore precision */
1512 	  if (key == '.')
1513 	    {
1514 	      key = *(++code);
1515 	      codetext = cstring_appendChar (codetext, key);
1516 	      fileloc_incColumn (formatloc);
1517 
1518 	      /*
1519 	      ** In printf, '*' means: read the next arg as an int for the
1520 	      ** field width.  This seems to be missing from my copy of the
1521 	      ** standard x3.159-1989.  Setion 4.9.6.1 refers to * (described
1522 	      ** later) but never does.
1523 	      */
1524 
1525 	      if (key == '*')
1526 		{
1527 		  ; /* don't do anything --- handle later */
1528 		}
1529 	      else
1530 		{
1531 		  while (isdigit ((int) key) != 0)
1532 		    {
1533 		      key = *(++code);
1534 		      codetext = cstring_appendChar (codetext, key);
1535 		      fileloc_incColumn (formatloc);
1536 		    }
1537 		}
1538 	    }
1539 
1540           if (key == 'h')
1541             {
1542               modtype = ctype_sint;  /* short */
1543               key = *(++code);
1544 	      codetext = cstring_appendChar (codetext, key);
1545 	      fileloc_incColumn (formatloc);
1546             }
1547           else if (key == 'l' || key == 'L')
1548             {
1549               modtype = ctype_lint; /* long */
1550               key = *(++code);
1551 	      codetext = cstring_appendChar (codetext, key);
1552 	      fileloc_incColumn (formatloc);
1553 
1554 	      if (key == 'l' || key == 'L') {
1555 		modtype = ctype_llint; /* long long */
1556 		key = *(++code);
1557 		codetext = cstring_appendChar (codetext, key);
1558 		fileloc_incColumn (formatloc);
1559 	      }
1560             }
1561 	  else
1562 	    {
1563 	      ; /* no modifier */
1564 	    }
1565 
1566           /* now, key = type of conversion to apply */
1567           ++code;
1568 	  fileloc_incColumn (formatloc);
1569 
1570           if (key != '%')
1571             {
1572 	      if (i >= nargs)
1573 		{
1574 		  if (optgenerror
1575 		      (FLG_TYPE,
1576 		       message ("No argument corresponding to %q format "
1577 				"code %d (%%%s): \"%s\"",
1578 				uentry_getName (fcn),
1579 				i, codetext,
1580 				cstring_fromChars (format)),
1581 		       f->loc))
1582 		    {
1583 		      if (fileloc_isDefined (formatloc)
1584 			  && context_getFlag (FLG_SHOWCOL))
1585 			{
1586 			  llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1587 					  formatloc);
1588 			}
1589 		    }
1590 		  i++;
1591 		}
1592 	      else
1593 		{
1594 		  a = exprNodeList_getN (args, i);
1595 		  i++;
1596 
1597 		  if (!exprNode_isError (a))
1598 		    {
1599 		      ctype expecttype;
1600 
1601 		      switch (key)
1602 			{
1603 			case '*': /* int argument for fieldwidth */
1604 			  expecttype = ctype_int;
1605 			  *(--code) = '%'; /* convert it for next code */
1606 			  fileloc_subColumn (formatloc, 1);
1607 			  /*@switchbreak@*/ break;
1608 			case 'u':
1609 			case 'o':
1610 			  expecttype = ctype_combine (ctype_uint, modtype);
1611 			  /*@switchbreak@*/ break;
1612 
1613 			case 'i': /* int argument */
1614 			case 'd':
1615 			  expecttype = ctype_combine (ctype_int, modtype);
1616 			  /*@switchbreak@*/ break;
1617 
1618 			case 'x': /* unsigned int */
1619 			case 'X':
1620 			  expecttype = ctype_combine (ctype_uint, modtype);
1621 
1622 			  /*@switchbreak@*/ break;
1623 
1624 			case 'e':
1625 			case 'E':
1626 			case 'g':
1627 			case 'G':
1628 			case 'f': /* double */
1629 			  expecttype = ctype_combine (ctype_double, modtype);
1630 			  /*@switchbreak@*/ break;
1631 
1632 			case 'c': /* int converted to char (check its a char?) */
1633 			  expecttype = ctype_makeConj (ctype_int,
1634 						       ctype_makeConj (ctype_char,
1635 								       ctype_uchar));
1636 			  /* evans 2001-10-05 - changed to reflect correct ISO spec:
1637 			     int converted to char */
1638 
1639 			  /*@switchbreak@*/ break;
1640 
1641 			case 's': /* string */
1642 			  expecttype = ctype_string;
1643 			  /*@switchbreak@*/ break;
1644 			case '[':
1645 			  /* skip to ']' */
1646 			  while (((key = *(++code)) != ']')
1647 				 && (key != '\0'))
1648 			    {
1649 			      codetext = cstring_appendChar (codetext, key);
1650 			      fileloc_incColumn (formatloc);
1651 			    }
1652 
1653 			  if (key == '\0')
1654 			    {
1655 			      llfatalerrorLoc
1656 				(message ("Bad character set format: %s",
1657 					  cstring_fromChars (origcode)));
1658 			    }
1659 
1660 			  expecttype = ctype_string;
1661 			  /*@switchbreak@*/ break;
1662 
1663 			case 'p': /* pointer */
1664 			  expecttype = ctype_makePointer (ctype_void);
1665 			  /* need not be defined */
1666 			  uentry_setDefState (regArg, SS_RELDEF);
1667 			  sRef_setPosNull (uentry_getSref (regArg),
1668 					   fileloc_undefined);
1669 			  /* could be null */
1670 			  /*@switchbreak@*/ break;
1671 
1672 			case 'n': /* pointer to int, modified by call! */
1673 			  expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1674 			  modified = TRUE;
1675 			  uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1676 			  /*@switchbreak@*/ break;
1677 
1678 			case 'm': /* in a syslog, it doesn't consume an argument */
1679 			  /* should check we're really doing syslog */
1680 
1681 			  /*@switchbreak@*/ break;
1682 
1683 
1684 			default:
1685 			  expecttype = ctype_unknown;
1686 
1687 			  voptgenerror
1688 			    (FLG_FORMATCODE,
1689 			     message ("Unrecognized format code: %s",
1690 				      cstring_fromChars (origcode)),
1691 			     fileloc_isDefined (formatloc)
1692 			     ? formatloc : g_currentloc);
1693 
1694 			  /*@switchbreak@*/ break;
1695 			}
1696 
1697 		      if (!(exprNode_matchArgType (expecttype, a)))
1698 			{
1699 			  if (ctype_isVoidPointer (expecttype)
1700 			      && ctype_isRealAbstract (a->typ)
1701 			      && (context_getFlag (FLG_ABSTVOIDP)))
1702 			    {
1703 			      ;
1704 			    }
1705 			  else
1706 			    {
1707 			      if (llgenformattypeerror
1708 				  (expecttype, exprNode_undefined,
1709 				   a->typ, a,
1710 				   message ("Format argument %d to %q (%%%s) expects "
1711 					    "%t gets %t: %s",
1712 					    i - argno,
1713 					    uentry_getName (fcn),
1714 					    codetext,
1715 					    expecttype,
1716 					    a->typ, exprNode_unparse (a)),
1717 				   a->loc))
1718 				{
1719 				  if (fileloc_isDefined (formatloc)
1720 				      && context_getFlag (FLG_SHOWCOL))
1721 				    {
1722 				      llgenindentmsg
1723 					(cstring_makeLiteral
1724 					 ("Corresponding format code"),
1725 					 formatloc);
1726 				    }
1727 				}
1728 			    }
1729 			}
1730 
1731 		      uentry_setType (regArg, expecttype);
1732 		      checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1733 
1734 		      if (ctype_equal (expecttype, ctype_string))
1735 			{
1736 			  exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1737 			}
1738 
1739 		      uentry_setType (regArg, ctype_unknown);
1740 		      uentry_fixupSref (regArg);
1741 
1742 		      if (modified)
1743 			{
1744 			  exprNode_checkCallModifyVal (a->sref, args, f, ret);
1745 			}
1746 		    }
1747 		  else
1748 		    {
1749 		      ;
1750 		    }
1751 		}
1752 	    }
1753 
1754 	  ocode = code;
1755 	  cstring_free (codetext);
1756 	}
1757 
1758       if (i < nargs)
1759 	{
1760 	  voptgenerror (FLG_TYPE,
1761 			message ("Format string for %q has %d arg%&, given %d",
1762 				 uentry_getName (fcn), i - argno, nargs - argno),
1763 			f->loc);
1764 	}
1765     }
1766   else
1767     {
1768       /* no checking possible for compile-time unknown format strings */
1769       if (exprNode_isDefined (a))
1770 	{
1771 	  voptgenerror
1772 	    (FLG_FORMATCONST,
1773 	     message ("Format string parameter to %s is not a compile-time constant: %s",
1774 		      exprNode_unparse (f),
1775 		      exprNode_unparse (a)),
1776 	     f->loc);
1777 	}
1778     }
1779 
1780   fileloc_free (formatloc);
1781 }
1782 
1783 static void
checkScanfArgs(exprNode f,uentry fcn,exprNodeList args,exprNode ret,int argno)1784 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1785 		 exprNodeList args, exprNode ret, int argno)
1786 {
1787   int i = argno;
1788   fileloc formatloc;
1789   int nargs = exprNodeList_size (args);
1790   uentryList params = uentry_getParams (fcn);
1791   exprNode a;
1792 
1793   /*
1794   ** These should be ensured by checkSpecialFunction
1795   */
1796 
1797   llassert (uentryList_size (params) == argno + 1);
1798   llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1799 
1800   a = exprNodeList_getN (args, argno - 1);
1801   formatloc = fileloc_copy (exprNode_loc (a));
1802 
1803   if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1804       && exprNode_knownStringValue (a))
1805     {
1806       char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1807       char *code = format;
1808       char *ocode = code;
1809 
1810       nargs = exprNodeList_size (args);
1811 
1812       while ((code = strchr (code, '%')) != NULL)
1813         {
1814           char *origcode = code;
1815           char key = *(++code);
1816 	  cstring codetext = cstring_newEmpty ();
1817           ctype modtype = ctype_int;
1818 	  char modifier = '\0';
1819           bool modified = TRUE;
1820 	  bool ignore = FALSE;
1821 
1822 	  codetext = cstring_appendChar (codetext, key);
1823 	  fileloc_addColumn (formatloc, code - ocode);
1824 
1825 	  /*
1826 	  ** this is based on ANSI standard library description of fscanf
1827 	  ** (from ANSI standard X3.159-1989, 4.9.6.1)
1828 	  */
1829 
1830 	  /* '*' suppresses assignment (does not need match argument) */
1831 
1832 	  if (key == '*')
1833 	    {
1834 	      key = *(++code);
1835 	      codetext = cstring_appendChar (codetext, key);
1836 	      modified = FALSE;
1837 	      ignore = TRUE;
1838 	      fileloc_incColumn (formatloc);
1839 	    }
1840 
1841 	  /* ignore field width */
1842 	  while (isdigit ((int) key) != 0)
1843 	    {
1844 	      key = *(++code);
1845 	      codetext = cstring_appendChar (codetext, key);
1846 	      fileloc_incColumn (formatloc);
1847 	    }
1848 
1849           if (key == 'h')
1850             {
1851               modtype = ctype_sint;  /* short */
1852               key = *(++code);
1853 	      codetext = cstring_appendChar (codetext, key);
1854 	      fileloc_incColumn (formatloc);
1855             }
1856           else if (key == 'l' || key == 'L')
1857             {
1858               modtype = ctype_lint; /* long */
1859 	      modifier = key;
1860 
1861               key = *(++code);
1862 	      codetext = cstring_appendChar (codetext, key);
1863 
1864 	      fileloc_incColumn (formatloc);
1865 
1866 	      if (key == 'l' || key == 'L') {
1867 		modtype = ctype_llint; /* long long */
1868 		key = *(++code);
1869 		codetext = cstring_appendChar (codetext, key);
1870 		fileloc_incColumn (formatloc);
1871 	      }
1872             }
1873 	  else
1874 	    {
1875 	      ; /* no modifier */
1876 	    }
1877 
1878           /* now, key = type of conversion to apply */
1879           ++code;
1880 	  fileloc_incColumn (formatloc);
1881 
1882           if (key != '%')
1883             {
1884 	      if (ignore)
1885 		{
1886 		  ;
1887 		}
1888 	      else
1889 		{
1890 		  if (i >= nargs)
1891 		    {
1892 		      if (optgenerror
1893 			  (FLG_TYPE,
1894 			   message ("No argument corresponding to %q format "
1895 				    "code %d (%%%s): \"%s\"",
1896 				    uentry_getName (fcn),
1897 				    i, codetext,
1898 				    cstring_fromChars (format)),
1899 			   f->loc))
1900 			{
1901 			  if (fileloc_isDefined (formatloc)
1902 			      && context_getFlag (FLG_SHOWCOL))
1903 			    {
1904 			      llgenindentmsg
1905 				(cstring_makeLiteral ("Corresponding format code"),
1906 				 formatloc);
1907 			    }
1908 			}
1909 		      i++;
1910 		    }
1911 		  else
1912 		    {
1913 		      a = exprNodeList_getN (args, i);
1914 		      i++;
1915 
1916 		      if (!exprNode_isError (a))
1917 			{
1918 			  ctype expecttype;
1919 
1920 			  switch (key)
1921 			    {
1922 			    case '*': /* int argument for fieldwidth */
1923 			      expecttype = ctype_makePointer (ctype_int);
1924 			      *(--code) = '%'; /* convert it for next code */
1925 			      fileloc_subColumn (formatloc, 1);
1926 			      /*@switchbreak@*/ break;
1927 			    case 'u':
1928 			    case 'o':
1929 			      expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1930 			      /*@switchbreak@*/ break;
1931 
1932 			    case 'i':
1933 			    case 'd':
1934 			      expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1935 			      /*@switchbreak@*/ break;
1936 
1937 			    case 'x':
1938 			    case 'X': /* unsigned int */
1939 			      expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1940 			      /*@switchbreak@*/ break;
1941 
1942 			    case 'e':
1943 			    case 'E':
1944 			    case 'g':
1945 			    case 'G':
1946 			    case 'f':
1947 			      /* printf is double, scanf is float! */
1948 
1949 			      if (modifier == 'l')
1950 				{
1951 				  expecttype = ctype_makePointer (ctype_double);
1952 				}
1953 			      else if (modifier == 'L')
1954 				{
1955 				  expecttype = ctype_makePointer (ctype_ldouble);
1956 				}
1957 			      else
1958 				{
1959 				  llassert (modifier == '\0');
1960 				  expecttype = ctype_makePointer (ctype_float);
1961 				}
1962 			      /*@switchbreak@*/ break;
1963 
1964 			    case 'c': /* int converted to char (check its a char?) */
1965 			      expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1966 			      /*@switchbreak@*/ break;
1967 
1968 			    case 's': /* string */
1969 			      expecttype = ctype_string;
1970 			      /*@switchbreak@*/ break;
1971 
1972 			    case '[':
1973 			      /* skip to ']' */
1974 			      while (((key = *(++code)) != ']')
1975 				     && (key != '\0'))
1976 				{
1977 				  codetext = cstring_appendChar (codetext, key);
1978 				  fileloc_incColumn (formatloc);
1979 				}
1980 
1981 			      if (key == '\0')
1982 				{
1983 				  llfatalerrorLoc
1984 				    (message ("Bad character set format: %s",
1985 					      cstring_fromChars (origcode)));
1986 				}
1987 
1988 			      expecttype = ctype_string;
1989 			      /*@switchbreak@*/ break;
1990 
1991 
1992 			    case 'p': /* pointer */
1993 			      voptgenerror
1994 				(FLG_FORMATCODE,
1995 				 message ("Format code should not be used in scanf: %s",
1996 					  cstring_fromChars (origcode)),
1997 				 fileloc_isDefined (formatloc)
1998 				 ? formatloc : g_currentloc);
1999 
2000 			      expecttype = ctype_unknown;
2001 			      /*@switchbreak@*/ break;
2002 
2003 			    case 'n': /* pointer to int, modified by call! */
2004 			      expecttype = ctype_makePointer (ctype_int);
2005 			      /*@switchbreak@*/ break;
2006 
2007 			    default:
2008 			      expecttype = ctype_unknown;
2009 
2010 			      voptgenerror
2011 				(FLG_FORMATCODE,
2012 				 message ("Unrecognized format code: %s",
2013 					  cstring_fromChars (origcode)),
2014 				 fileloc_isDefined (formatloc)
2015 				 ? formatloc : g_currentloc);
2016 
2017 			      /*@switchbreak@*/ break;
2018 			    }
2019 
2020 			  if (!(exprNode_matchArgType (expecttype, a)))
2021 			    {
2022 			      if (ctype_isVoidPointer (expecttype)
2023 				  && ctype_isRealAbstract (a->typ)
2024 				  && (context_getFlag (FLG_ABSTVOIDP)))
2025 				{
2026 				  ;
2027 				}
2028 			      else
2029 				{
2030 				  if (llgenformattypeerror
2031 				      (expecttype, exprNode_undefined,
2032 				       a->typ, a,
2033 				       message ("Format argument %d to %q (%%%s) expects "
2034 						"%t gets %t: %s",
2035 						i - argno,
2036 						uentry_getName (fcn),
2037 						codetext, expecttype,
2038 						a->typ, exprNode_unparse (a)),
2039 				       a->loc))
2040 				    {
2041 				      if (fileloc_isDefined (formatloc)
2042 					  && context_getFlag (FLG_SHOWCOL))
2043 					{
2044 					  llgenindentmsg
2045 					    (cstring_makeLiteral
2046 					     ("Corresponding format code"),
2047 					     formatloc);
2048 					}
2049 				    }
2050 				}
2051 			    }
2052 
2053 			  uentry_setType (outArg, expecttype);
2054 			  checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2055 			  uentry_setType (outArg, ctype_unknown);
2056 			  uentry_fixupSref (outArg);
2057 
2058 			  if (modified)
2059 			    {
2060 			      exprNode_checkCallModifyVal (a->sref, args, f, ret);
2061 			    }
2062 			}
2063 		      else
2064 			{
2065 			  			  /* a->sref = sRef_undefined; */
2066 			}
2067 		    }
2068 		}
2069 	    }
2070 
2071 	  ocode = code;
2072 	  cstring_free (codetext);
2073 	}
2074 
2075       if (i < nargs)
2076 	{
2077 	  voptgenerror (FLG_TYPE,
2078 			message ("Format string for %q has %d arg%&, given %d",
2079 				 uentry_getName (fcn), i - argno, nargs - argno),
2080 			f->loc);
2081 	}
2082     }
2083   else
2084     {
2085       /* no checking possible for compile-time unknown format strings */
2086     }
2087 
2088   fileloc_free (formatloc);
2089 }
2090 
2091 static void
checkMessageArgs(exprNode f,uentry fcn,exprNodeList args,int argno)2092 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2093 		  uentry fcn,
2094 		  exprNodeList args,
2095 		  /*@unused@*/ int argno)
2096 {
2097   /*
2098   ** the last argument before the elips is the format string
2099   */
2100 
2101   int nargs = exprNodeList_size (args);
2102   int i = argno;
2103   fileloc formatloc;
2104   exprNode a;
2105 
2106   a = exprNodeList_getN (args, argno - 1);
2107   formatloc = fileloc_copy (exprNode_loc (a));
2108 
2109   if (ctype_isUnknown (cstringType)) {
2110     if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2111       {
2112 	cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2113       }
2114   }
2115 
2116   if (ctype_isUnknown (ctypeType)) {
2117     if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2118       {
2119 	ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2120       }
2121   }
2122 
2123   if (ctype_isUnknown (filelocType)) {
2124     if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2125       {
2126 	filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2127       }
2128   }
2129 
2130   if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2131       && exprNode_knownStringValue (a))
2132     {
2133       cstring format = multiVal_forceString (exprNode_getValue (a));
2134       char *code = cstring_toCharsSafe (format);
2135       char *ocode = code;
2136 
2137       nargs = exprNodeList_size (args);
2138 
2139       while ((code = strchr (code, '%')) != NULL)
2140         {
2141           char *origcode = code;
2142           char key = *(++code);
2143 	  cstring codetext = cstring_newEmpty ();
2144 	  bool isOnly = FALSE;
2145 
2146 	  codetext = cstring_appendChar (codetext, key);
2147 
2148 	  fileloc_addColumn (formatloc, code - ocode);
2149 
2150 	  while (key >= '0' && key <= '9')
2151 	    {
2152 	      key = *(++code);
2153 	      codetext = cstring_appendChar (codetext, key);
2154 	      fileloc_incColumn (formatloc);
2155 	    }
2156 
2157 	  ++code;
2158 	  fileloc_incColumn (formatloc);
2159 
2160           if (key != '%')
2161 	    {
2162 	      if (key == '&') /* plural marker */
2163 		{
2164 		  goto nextKey;
2165 		}
2166 
2167 	      if (i >= nargs)
2168 		{
2169 		  voptgenerror
2170 		    (FLG_TYPE,
2171 		     message ("Message missing format arg %d (%%%s): \"%s\"",
2172 			      i + 1, codetext, format),
2173 		     f->loc);
2174 		  i++;
2175 		}
2176 	      else
2177 		{
2178 		  a = exprNodeList_getN (args, i);
2179 		  i++;
2180 
2181 		nextKey:
2182 		  if (!exprNode_isError (a))
2183 		    {
2184 		      ctype expecttype;
2185 
2186 		      /*@-loopswitchbreak@*/
2187 
2188 		      switch (key)
2189 			{
2190 			case 'c':
2191 			case 'h':
2192 			  expecttype = ctype_char; break;
2193 			case 's':
2194 			  expecttype = cstringType; break;
2195 			case 'q':
2196 			  expecttype = cstringType; isOnly = TRUE; break;
2197 			case 'x':
2198 			  expecttype = cstringType; isOnly = TRUE; break;
2199 			case 'd': expecttype = ctype_int; break;
2200 			case 'u': expecttype = ctype_uint; break;
2201 			case 'w': expecttype = ctype_ulint; break;
2202 			case 'f': expecttype = ctype_float; break;
2203 			case 'b': expecttype = ctype_bool; break;
2204 			case 't': expecttype = ctypeType; break;
2205 			case 'p':
2206 			  expecttype = ctype_makePointer (ctype_void);
2207 			  /* need not be defined */
2208 			  uentry_setDefState (regArg, SS_RELDEF);
2209 			  sRef_setPosNull (uentry_getSref (regArg),
2210 					   fileloc_undefined);
2211 			  /* could be null */
2212 			  /*@switchbreak@*/ break;
2213 			case 'l': expecttype = filelocType; break;
2214 			case '&':  /* a wee bit of a hack methinks */
2215 			  expecttype = ctype_int;
2216 			  break;
2217 			case 'r': expecttype = ctype_bool; break;
2218 			default:
2219 			  expecttype = ctype_unknown;
2220 			  voptgenerror
2221 			    (FLG_FORMATCODE,
2222 			     message ("Unrecognized format code: %s",
2223 				      cstring_fromChars (origcode)),
2224 			     fileloc_isDefined (formatloc)
2225 			     ? formatloc : g_currentloc);
2226 			  break;
2227 			}
2228 		      /*@=loopswitchbreak@*/
2229 
2230 		      if (!(exprNode_matchArgType (expecttype, a)))
2231 			{
2232 			  if (ctype_isVoidPointer (expecttype)
2233 			      && ctype_isRealAbstract (a->typ)
2234 			      && (context_getFlag (FLG_ABSTVOIDP)))
2235 			    {
2236 			      ;
2237 			    }
2238 			  else
2239 			    {
2240 			      if (llgenformattypeerror
2241 				  (expecttype, exprNode_undefined,
2242 				   a->typ, a,
2243 				   message ("Format argument %d to %q (%%%s) expects "
2244 					    "%t gets %t: %s",
2245 					    i - argno,
2246 					    uentry_getName (fcn),
2247 					    codetext, expecttype,
2248 					    a->typ, exprNode_unparse (a)),
2249 				   a->loc))
2250 				{
2251 				  if (fileloc_isDefined (formatloc)
2252 				      && context_getFlag (FLG_SHOWCOL))
2253 				    {
2254 				      llgenindentmsg
2255 					(cstring_makeLiteral
2256 					 ("Corresponding format code"),
2257 					 formatloc);
2258 				    }
2259 				}
2260 			    }
2261 			}
2262 
2263 		      if (ctype_equal (expecttype, cstringType))
2264 			{
2265 			  if (isOnly)
2266 			    {
2267 			      checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2268 			      uentry_fixupSref (csOnlyArg);
2269 			    }
2270 			  else
2271 			    {
2272 			      checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2273 			      uentry_fixupSref (csArg);
2274 			    }
2275 			}
2276 		      else
2277 			{
2278 			  			  checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2279 			  uentry_fixupSref (regArg);
2280 			}
2281 		    }
2282 		}
2283 	    }
2284 
2285 	  cstring_free (codetext);
2286 	}
2287 
2288       if (i < nargs)
2289 	{
2290 	  voptgenerror (FLG_TYPE,
2291 			message ("Format string for %q has %d arg%&, given %d",
2292 				 uentry_getName (fcn), i - argno, nargs -argno),
2293 			f->loc);
2294 	}
2295     }
2296   else
2297     {
2298       /* no checking possible for compile-time unknown format strings */
2299     }
2300 
2301   fileloc_free (formatloc);
2302 }
2303 
2304 static void
checkExpressionDefinedAux(exprNode e1,exprNode e2,sRefSet sets1,sRefSet sets2,lltok op,flagcode flag)2305   checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2306 			     /*@notnull@*/ exprNode e2,
2307 			     sRefSet sets1,
2308 			     sRefSet sets2,
2309 			     lltok op,
2310 			     flagcode flag)
2311 {
2312   bool hadUncon = FALSE;
2313 
2314   if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2315       sRefSet_hasUnconstrained (sets2))
2316     {
2317       voptgenerror
2318 	(FLG_EVALORDERUNCON,
2319 	 message
2320 	 ("Expression may have undefined behavior (%q used in right operand "
2321 	  "may set global variable %q used in left operand): %s %s %s",
2322 	  sRefSet_unparseUnconstrained (sets2),
2323 	  sRef_unparse (sRef_getRootBase (e1->sref)),
2324 	  exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2325 	 e2->loc);
2326     }
2327 
2328   if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2329       sRefSet_hasUnconstrained (sets1))
2330     {
2331       voptgenerror
2332 	(FLG_EVALORDERUNCON,
2333 	 message
2334 	 ("Expression has undefined behavior (%q used in left operand "
2335 	  "may set global variable %q used in right operand): %s %s %s",
2336 	  sRefSet_unparseUnconstrained (sets1),
2337 	  sRef_unparse (e2->sref),
2338 	  exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2339 	 e2->loc);
2340     }
2341 
2342   sRefSet_realElements (e1->uses, sr)
2343     {
2344       if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2345 	{
2346 	  voptgenerror
2347 	    (FLG_EVALORDER,
2348 	     message
2349 	     ("Expression has undefined behavior (left operand uses %q, "
2350 	      "modified by right operand): %s %s %s",
2351 	      sRef_unparse (sr),
2352 	      exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2353 	     e2->loc);
2354 	}
2355     } end_sRefSet_realElements;
2356 
2357   sRefSet_realElements (sets1, sr)
2358     {
2359       if (sRef_isMeaningful (sr))
2360 	{
2361 	  if (sRef_same (sr, e2->sref))
2362 	    {
2363 	      voptgenerror
2364 		(flag,
2365 		 message
2366 		 ("Expression has undefined behavior (value of right operand "
2367 		  "modified by left operand): %s %s %s",
2368 		  exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2369 		 e2->loc);
2370 	    }
2371 	  else if (sRefSet_member (e2->uses, sr))
2372 	    {
2373 	      voptgenerror
2374 		(flag,
2375 		 message
2376 		 ("Expression has undefined behavior (left operand modifies %q, "
2377 		  "used by right operand): %s %s %s",
2378 		  sRef_unparse (sr),
2379 		  exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2380 		 e2->loc);
2381 	    }
2382 	  else
2383 	    {
2384 	      if (sRefSet_member (sets2, sr))
2385 		{
2386 		  if (sRef_isUnconstrained (sr))
2387 		    {
2388 		      if (hadUncon)
2389 			{
2390 			  ;
2391 			}
2392 		      else
2393 			{
2394 			  hadUncon = optgenerror
2395 			    (FLG_EVALORDERUNCON,
2396 			     message
2397 			     ("Expression may have undefined behavior.  Left operand "
2398 			      "calls %q; right operand calls %q.  The unconstrained "
2399 			      "functions may modify global state used by "
2400 			      "the other operand): %s %s %s",
2401 			      sRefSet_unparseUnconstrained (sets1),
2402 			      sRefSet_unparseUnconstrained (sets2),
2403 			      exprNode_unparse (e1), lltok_unparse (op),
2404 			      exprNode_unparse (e2)),
2405 			     e2->loc);
2406 			}
2407 		    }
2408 		  else
2409 		    {
2410 		      voptgenerror
2411 			(flag,
2412 			 message
2413 			 ("Expression has undefined behavior (both "
2414 			  "operands modify %q): %s %s %s",
2415 			  sRef_unparse (sr),
2416 			  exprNode_unparse (e1),
2417 			  lltok_unparse (op), exprNode_unparse (e2)),
2418 			 e2->loc);
2419 		    }
2420 		}
2421 	    }
2422 	}
2423     } end_sRefSet_realElements;
2424 }
2425 
checkExpressionDefined(exprNode e1,exprNode e2,lltok op)2426 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2427 {
2428   bool hasError = FALSE;
2429 
2430   if (exprNode_isError (e1) || exprNode_isError (e2))
2431     {
2432       return;
2433     }
2434 
2435   if (sRefSet_member (e2->sets, e1->sref))
2436     {
2437       if (e2->kind == XPR_CALL)
2438 	{
2439 	 ;
2440 	}
2441       else
2442 	{
2443 	  hasError = optgenerror
2444 	    (FLG_EVALORDER,
2445 	     message ("Expression has undefined behavior "
2446 		      "(value of left operand %s is modified "
2447 		      "by right operand %s): %s %s %s",
2448 		      exprNode_unparse (e1),
2449 		      exprNode_unparse (e2),
2450 		      exprNode_unparse (e1), lltok_unparse (op),
2451 		      exprNode_unparse (e2)),
2452 	     e2->loc);
2453 	}
2454     }
2455 
2456   if (context_getFlag (FLG_EVALORDERUNCON))
2457     {
2458       if (sRefSet_member (e2->msets, e1->sref))
2459 	{
2460 	  if (e2->kind == XPR_CALL)
2461 	    {
2462 	      ;
2463 	    }
2464 	  else
2465 	    {
2466 	      hasError = optgenerror
2467 		(FLG_EVALORDER,
2468 		 message
2469 		 ("Expression has undefined behavior (value of left "
2470 		  "operand may be modified by right operand): %s %s %s",
2471 		  exprNode_unparse (e1), lltok_unparse (op),
2472 		  exprNode_unparse (e2)),
2473 		 e2->loc);
2474 	    }
2475 	}
2476     }
2477 
2478   if (!hasError)
2479     {
2480       checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2481 
2482       if (context_maybeSet (FLG_EVALORDERUNCON))
2483 	{
2484 	  checkExpressionDefinedAux (e1, e2, e1->msets,
2485 				     e2->msets, op, FLG_EVALORDERUNCON);
2486 	}
2487     }
2488 }
2489 
2490 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2491 
2492 static int
checkArgsReal(uentry fcn,exprNode f,uentryList cl,exprNodeList args,bool isIter,exprNode ret)2493   checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2494 		 exprNodeList args, bool isIter, exprNode ret)
2495 {
2496   int special = 0;
2497 
2498   if (!exprNode_isError (f))
2499     {
2500       if (!uentryList_isMissingParams (cl))
2501         {
2502           int nargs = exprNodeList_size (args);
2503           int expectargs = uentryList_size (cl);
2504           ctype last;
2505           int i = 0;
2506 
2507           if (expectargs == 0)
2508             {
2509               if (nargs != 0)
2510 		{
2511 		  if (isIter)
2512 		    {
2513 		      voptgenerror
2514 			(FLG_TYPE,
2515 			 message ("Iter %q invoked with %d args, "
2516 				  "declared void",
2517 				  uentry_getName (fcn),
2518 				  nargs),
2519 			 f->loc);
2520 		    }
2521 		  else
2522 		    {
2523 		      voptgenerror
2524 			(FLG_TYPE,
2525 			 message ("Function %s called with %d args, "
2526 				  "declared void",
2527 				  exprNode_unparse (f), nargs),
2528 			 f->loc);
2529 		    }
2530 		}
2531               return special;
2532             }
2533 
2534           last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2535 
2536           exprNodeList_reset (args);
2537 
2538           uentryList_elements (cl, current)
2539             {
2540               ctype ct = uentry_getType (current);
2541               exprNode a;
2542 
2543               if (ctype_isElips (ct))
2544 		{
2545 		  /*
2546 		   ** do special checking for printf/scanf library functions
2547 		   **
2548 		   ** this is kludgey code, just for handling the special case
2549 		   **
2550 		   */
2551 
2552 		  if (uentry_isPrintfLike (fcn))
2553 		    {
2554 		      checkPrintfArgs (f, fcn, args, ret, i);
2555 		      special = i;
2556 		    }
2557 		  else if (uentry_isScanfLike (fcn))
2558 		    {
2559 		      checkScanfArgs (f, fcn, args, ret, i);
2560 		      special = i;
2561 		    }
2562 		  else if (uentry_isMessageLike (fcn))
2563 		    {
2564 		      checkMessageArgs (f, fcn, args, i);
2565 		      special = i;
2566 		    }
2567 		  else
2568 		    {
2569 		      llassert (!uentry_isSpecialFunction (fcn));
2570 		    }
2571 
2572 		  nargs = expectargs; /* avoid errors */
2573 		  break;
2574 		}
2575               else
2576 		{
2577 		  if (i >= nargs) break;
2578 
2579 		  a = exprNodeList_current (args);
2580 		  exprNodeList_advance (args);
2581 
2582 		  i++;
2583 
2584 		  if (exprNode_isError (a))
2585 		    {
2586 		     ;
2587 		    }
2588 		  else
2589 		    {
2590 		      /*
2591 			probably necessary? I'm not sure about this one
2592 			checkMacroParen (a);
2593 			*/
2594 
2595 		      f->guards = guardSet_union (f->guards, a->guards);
2596 
2597 		      DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2598 
2599 		      if (!(exprNode_matchArgType (ct, a)))
2600 			{
2601 			  DPRINTF (("Args mismatch!"));
2602 
2603 			  if (ctype_isVoidPointer (ct)
2604 			      && (ctype_isPointer (a->typ)
2605 				  && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2606 			    {
2607 			      vnoptgenerror
2608 				(FLG_ABSTVOIDP,
2609 				 message
2610 				 ("Pointer to abstract type (%t) used "
2611 				  "as void pointer "
2612 				  "(arg %d to %q): %s",
2613 				  a->typ, i,
2614 				  uentry_getName (fcn),
2615 				  exprNode_unparse (a)),
2616 				 a->loc);
2617 			    }
2618 			  else
2619 			    {
2620 			      if (isIter)
2621 				{
2622 				  (void) gentypeerror
2623 				    (ct, exprNode_undefined,
2624 				     a->typ, a,
2625 				     message
2626 				     ("Iter %q expects arg %d to "
2627 				      "be %t gets %t: %s",
2628 				      uentry_getName (fcn),
2629 				      i, ct, a->typ, exprNode_unparse (a)),
2630 				     a->loc);
2631 				}
2632 			      else
2633 				{
2634 				  if (gentypeerror
2635 				      (ct,
2636 				       exprNode_undefined,
2637 				       a->typ,
2638 				       a,
2639 				       message
2640 				       ("Function %q expects arg %d to be %t gets %t: %s",
2641 					uentry_getName (fcn),
2642 					i, ct, a->typ, exprNode_unparse (a)),
2643 				       a->loc))
2644 				    {
2645 				      DPRINTF (("Types: %s / %s",
2646 						ctype_unparse (ct),
2647 						ctype_unparse (a->typ)));
2648 				    }
2649 
2650 				  /*
2651 				  ** Clear null marker for abstract types.
2652 				  ** (It is not revealed, so suppress future messages.)
2653 				  */
2654 
2655 				  if (ctype_isAbstract (a->typ))
2656 				    {
2657 				      sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2658 				    }
2659 				}
2660 			    }
2661 			}
2662 		    }
2663 		}
2664             } end_uentryList_elements ;
2665 
2666 
2667 	  if (expectargs != nargs) /* note: not != since we may have ... */
2668 	    {
2669 	      if (ctype_isElips (last))
2670 		{
2671 		  voptgenerror
2672 		    (FLG_TYPE,
2673 		     message ("Function %s called with %d args, expects at least %d",
2674 			      exprNode_unparse (f),
2675 			      nargs, expectargs - 1),
2676 		     f->loc);
2677 		}
2678 	      else
2679 		{
2680 		  if (isIter)
2681 		    {
2682 		      voptgenerror
2683 			(FLG_TYPE,
2684 			 message ("Iter %q invoked with %d args, expects %d",
2685 				  uentry_getName (fcn), nargs, expectargs),
2686 			 f->loc);
2687 		    }
2688 		  else
2689 		    {
2690 		      voptgenerror
2691 			(FLG_TYPE,
2692 			 message ("Function %s called with %d args, expects %d",
2693 				  exprNode_unparse (f),
2694 				  nargs, expectargs),
2695 			 f->loc);
2696 		    }
2697 		}
2698 	    }
2699         }
2700     }
2701 
2702   return special;
2703 }
2704 
2705 /*
2706 ** Check for undefined code sequences in function arguments:
2707 **
2708 **   one parameter sets something used by another parameter
2709 **   one parameter sets something set  by another parameter
2710 */
2711 
2712 static void
checkSequencingOne(exprNode f,exprNodeList args,exprNode el,int argno)2713 checkSequencingOne (exprNode f, exprNodeList args,
2714 		    /*@notnull@*/ exprNode el, int argno)
2715 {
2716   /*
2717   ** Do second loop, iff +undefunspec
2718   */
2719 
2720   int checkloop;
2721   int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2722 
2723   for (checkloop = 0; checkloop < numloops; checkloop++)
2724     {
2725       sRefSet thissets;
2726 
2727       if (checkloop == 0)
2728 	{
2729 	  thissets = el->sets;
2730 	}
2731       else
2732 	{
2733 	  llassert (checkloop == 1);
2734 	  thissets = el->msets;
2735 	}
2736 
2737       sRefSet_realElements (thissets, thisset)
2738 	{
2739 	  int j;
2740 
2741 	  /*@access exprNodeList@*/
2742 	  for (j = 0; j < args->nelements; j++)
2743 	    {
2744 	      exprNode jl = args->elements[j];
2745 	      int thisargno = j + 1;
2746 
2747 	      if (thisargno != argno && exprNode_isDefined (jl))
2748 		{
2749 		  sRefSet otheruses = jl->uses;
2750 
2751 		  if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2752 		      sRefSet_hasUnconstrained (thissets))
2753 		    {
2754 		      voptgenerror
2755 			(FLG_EVALORDERUNCON,
2756 			 /*@-sefparams@*/
2757 			 message
2758 			 ("%q used in argument %d may set "
2759 			  "global variable %q used by argument %d: %s(%q)",
2760 			  cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2761 			  /*@=sefparams@*/
2762 			  argno,
2763 			  sRef_unparse (sRef_getRootBase (jl->sref)),
2764 			  thisargno,
2765 			  exprNode_unparse (f), exprNodeList_unparse (args)),
2766 			 el->loc);
2767 		    }
2768 
2769 		  if (sRefSet_member (otheruses, thisset))
2770 		    {
2771 		      if (sRef_isUnconstrained (thisset))
2772 			{
2773 			  voptgenerror
2774 			    (FLG_EVALORDERUNCON,
2775 			     message
2776 			     ("Unconstrained functions used in arguments %d (%q) "
2777 			      "and %d (%s) may modify "
2778 			      "or use global state in undefined way: %s(%q)",
2779 			      argno,
2780 			      sRefSet_unparseUnconstrainedPlain (otheruses),
2781 			      thisargno,
2782 			      sRef_unconstrainedName (thisset),
2783 			      exprNode_unparse (f),
2784 			      exprNodeList_unparse (args)),
2785 			     el->loc);
2786 			}
2787 		      else
2788 			{
2789 			  voptgenerror
2790 			    (FLG_EVALORDER,
2791 			     message
2792 			     ("Argument %d modifies %q, used by argument %d "
2793 			      "(order of evaluation of actual parameters is "
2794 			      "undefined): %s(%q)",
2795 			      argno, sRef_unparse (thisset), thisargno,
2796 			      exprNode_unparse (f), exprNodeList_unparse (args)),
2797 			     el->loc);
2798 			}
2799 		    }
2800 		  else
2801 		    {
2802 		      sRefSet othersets = jl->sets;
2803 
2804 		      if (sRefSet_member (othersets, thisset))
2805 			{
2806 			  if (sRef_isUnconstrained (thisset))
2807 			    {
2808 			      voptgenerror
2809 				(FLG_EVALORDERUNCON,
2810 				 message
2811 				 ("Unconstrained functions used in "
2812 				  "arguments %d (%q) and %d (%s) may modify "
2813 				  "or use global state in undefined way: %s(%q)",
2814 				  argno,
2815 				  sRefSet_unparseUnconstrainedPlain (othersets),
2816 				  thisargno,
2817 				  sRef_unconstrainedName (thisset),
2818 				  exprNode_unparse (f), exprNodeList_unparse (args)),
2819 				 el->loc);
2820 			    }
2821 			  else
2822 			    {
2823 			      voptgenerror
2824 				(FLG_EVALORDER,
2825 				 message
2826 				 ("Argument %d modifies %q, set by argument %d (order of"
2827 				  " evaluation of actual parameters is undefined): %s(%q)",
2828 				  argno, sRef_unparse (thisset), thisargno,
2829 				  exprNode_unparse (f), exprNodeList_unparse (args)),
2830 				 el->loc);
2831 			    }
2832 			}
2833 		    }
2834 		}
2835 	    }
2836 	  /*@noaccess exprNodeList@*/
2837 	} end_sRefSet_realElements;
2838     }
2839 }
2840 
2841 static void
checkSequencing(exprNode f,exprNodeList args)2842 checkSequencing (exprNode f, exprNodeList args)
2843 {
2844   if (exprNodeList_size (args) > 1)
2845     {
2846       int i;
2847       exprNode el;
2848 
2849       /*@access exprNodeList*/
2850 
2851       for (i = 0; i < args->nelements; i++)
2852 	{
2853 	  el = args->elements[i];
2854 
2855 	  if (!exprNode_isError (el))
2856 	    {
2857 	      checkSequencingOne (f, args, el, i + 1);
2858 	    }
2859 	}
2860       /*@noaccess exprNodeList*/
2861     }
2862 }
2863 
2864 /*
2865 ** requires le = exprNode_getUentry (f)
2866 */
2867 
2868 static void
checkGlobMods(exprNode f,uentry le,exprNodeList args,exprNode ret,int specialArgs)2869 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2870 	       uentry le, exprNodeList args,
2871 	       /*@notnull@*/ exprNode ret, int specialArgs)
2872 {
2873   bool isSpec = FALSE;
2874   bool hasMods = FALSE;
2875   cstring fname;
2876   globSet usesGlobs = globSet_undefined;
2877   sRefSet mods = sRefSet_undefined;
2878   bool freshMods = FALSE;
2879   uentryList params = uentryList_undefined;
2880 
2881   DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2882 
2883   /*
2884   ** check globals and modifies
2885   */
2886 
2887   setCodePoint ();
2888 
2889   if (!uentry_isValid (le))
2890     {
2891       ctype fr = ctype_realType (f->typ);
2892 
2893       if (ctype_isFunction (fr))
2894         {
2895           params = ctype_argsFunction (fr);
2896         }
2897       else
2898         {
2899           params = uentryList_missingParams;
2900         }
2901 
2902       if (!context_getFlag (FLG_MODNOMODS)
2903 	  && !context_getFlag (FLG_GLOBUNSPEC))
2904         {
2905 	  checkUnspecCall (f, params, args);
2906         }
2907 
2908       return;
2909     }
2910 
2911   fname = uentry_rawName (le);
2912 
2913   setCodePoint ();
2914 
2915   if (uentry_isFunction (le))
2916     {
2917       params = uentry_getParams (le);
2918       mods = uentry_getMods (le);
2919       hasMods = uentry_hasMods (le);
2920       usesGlobs = uentry_getGlobs (le);
2921       isSpec = uentry_isSpecified (le);
2922     }
2923   else /* not a function */
2924     {
2925       ctype ct = ctype_realType (uentry_getType (le));
2926 
2927       llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2928 		     ("checkModGlobs: uentry not a function: %s",
2929 		      uentry_unparse (le)));
2930 
2931       params = ctype_argsFunction (ct);
2932       return; /* No checking for non-function */
2933     }
2934 
2935   /*
2936   ** check globals
2937   */
2938 
2939   setCodePoint ();
2940 
2941   globSet_allElements (usesGlobs, el)
2942     {
2943       if (sRef_isValid (el))
2944 	{
2945 	  if (sRef_isInternalState (el) || sRef_isSystemState (el))
2946 	    {
2947 	      context_usedGlobal (el);
2948 	      exprNode_checkUse (f, el, f->loc);
2949 
2950 	      if (context_checkInternalUse ())
2951 		{
2952 		  if (!context_globAccess (el))
2953 		    {
2954 		      if (sRef_isSystemState (el)
2955 			  && !context_getFlag (FLG_MODFILESYSTEM))
2956 			{
2957 			  ;
2958 			}
2959 		      else
2960 			{
2961 			  voptgenerror
2962 			    (FLG_INTERNALGLOBS,
2963 			     message
2964 			     ("Called procedure %s may access %q, but "
2965 			      "globals list does not include globals %s",
2966 			      exprNode_unparse (f),
2967 			      sRef_unparse (el),
2968 			      cstring_makeLiteralTemp (sRef_isInternalState (el)
2969 						       ? "internalState"
2970 						       : "fileSystem")),
2971 			     f->loc);
2972 			}
2973 		    }
2974 		}
2975 	    }
2976 	  else if (sRef_isNothing (el) || sRef_isSpecState (el))
2977 	    {
2978 	      ;
2979 	    }
2980 	  else
2981 	    {
2982 	      uentry gle = sRef_getUentry (el);
2983 	      sRef sr = sRef_updateSref (el);
2984 
2985 	      if (sRef_isUndefGlob (el))
2986 		{
2987 		  sRef_setDefined (sr, f->loc);
2988 		  exprNode_checkSet (f, sr);
2989 		}
2990 	      else
2991 		{
2992 		  /*
2993 		  ** check definition
2994 		  */
2995 
2996 		  if (sRef_isAllocated (el))
2997 		    {
2998 		      exprNode_checkSet (f, sr);
2999 		    }
3000 		  else
3001 		    {
3002 		      if (sRef_isStateUndefined (sr))
3003 			{
3004 			  voptgenerror
3005 			    (FLG_GLOBSTATE,
3006 			     message
3007 			     ("%s %q used by function undefined before call: %s",
3008 			      sRef_getScopeName (sr),
3009 			      sRef_unparse (sr),
3010 			      exprNode_unparse (f)),
3011 			     f->loc);
3012 			  sRef_setDefined (sr, f->loc);
3013 			}
3014 		      exprNode_checkUse (f, sr, f->loc);
3015 		    }
3016 
3017 		  checkGlobUse (gle, TRUE, f);
3018 		}
3019 
3020 	      if (sRef_isKilledGlob (el))
3021 		{
3022 		  sRef_kill (sr, f->loc);
3023 		  context_usedGlobal (sr);
3024 		}
3025 	    }
3026 	}
3027     } end_globSet_allElements;
3028 
3029   /*
3030   ** check modifies
3031   */
3032 
3033   if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
3034     {
3035       sRefSet smods = sRefSet_undefined;
3036 
3037       /*
3038       ** NEED to check for modifies anything
3039       */
3040 
3041       /*
3042       ** check each sRef that called function modifies (ml), is
3043       ** modifiable by tl
3044       */
3045 
3046       setCodePoint ();
3047 
3048       sRefSet_allElements (mods, s) /* s is something which may be modified */
3049         {
3050 	  DPRINTF (("Check modify: %s", sRef_unparse (s)));
3051 
3052 	  if (sRef_isKindSpecial (s))
3053 	    {
3054 	      if (sRef_isSpecInternalState (s))
3055 		{
3056 		  if (context_getFlag (FLG_MODINTERNALSTRICT))
3057 		    {
3058 		      exprNode_checkCallModifyVal (s, args, f, ret);
3059 		    }
3060 		  else
3061 		    {
3062 		      sRefSet mmods = context_modList ();
3063 
3064 		      sRefSet_allElements (mmods, el)
3065 			{
3066 			  if (sRef_isInternalState (el))
3067 			    {
3068 			      sRef_setModified (el);
3069 			    }
3070 			} end_sRefSet_allElements ;
3071 		    }
3072 		}
3073 	      else
3074 		{
3075 		  exprNode_checkCallModifyVal (s, args, f, ret);
3076 		}
3077 	    }
3078 	  else
3079 	    {
3080 	      sRef rb = sRef_getRootBase (s);
3081 
3082 	      if (sRef_isFileOrGlobalScope (rb))
3083 		{
3084 		  context_usedGlobal (rb);
3085 		}
3086 
3087 	      if (sRef_isFileStatic (s)
3088 		  && !fileId_equal (fileloc_fileId (f->loc),
3089 				    fileloc_fileId (uentry_whereDefined (le))))
3090 		{
3091 		  smods = sRefSet_insert (smods, s);
3092 		}
3093 	      else
3094 		{
3095 		  exprNode_checkCallModifyVal (s, args, f, ret);
3096 		}
3097 	    }
3098         } end_sRefSet_allElements;
3099 
3100       setCodePoint ();
3101 
3102       /*
3103       ** Static elements in modifies set can have nasty consequences.
3104       ** (I think...have not been able to reproduce a possible bug.)
3105       */
3106 
3107       if (!sRefSet_isDefined (smods))
3108 	{
3109 	  mods = sRefSet_newCopy (mods);
3110 	  freshMods = TRUE;
3111 
3112 	  sRefSet_allElements (smods, el)
3113 	    {
3114 	      bool res = sRefSet_delete (mods, el);
3115 
3116 	      llassert (res);
3117 	    } end_sRefSet_allElements;
3118 
3119 	  sRefSet_free (smods);
3120 	/*@-branchstate@*/
3121 	}
3122       /*@=branchstate@*/
3123     }
3124   else if (sRefSet_isDefined (mods))
3125     { /* just check observers */
3126       setCodePoint ();
3127 
3128       sRefSet_allElements (mods, s) /* s is something which may be modified */
3129         {
3130 	  sRef rb = sRef_getRootBase (s);
3131 
3132 	  setCodePoint ();
3133 
3134 	  if (sRef_isParam (rb))
3135 	    {
3136 	      sRef b = sRef_fixBaseParam (s, args);
3137 
3138 	      if (sRef_isObserver (b))
3139 		{
3140 		  exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3141 
3142 		  if (optgenerror
3143 		      (FLG_MODOBSERVER,
3144 		       message ("Function call may modify observer%q: %s",
3145 				sRef_unparsePreOpt (b), exprNode_unparse (e)),
3146 		       exprNode_loc (e)))
3147 		    {
3148 		      sRef_showExpInfo (b);
3149 		    }
3150 		}
3151 	    }
3152         } end_sRefSet_allElements;
3153     }
3154   else
3155     {
3156       if (!hasMods) /* no specified modifications */
3157 	{
3158 	  if (context_getFlag (FLG_MODOBSERVERUNCON))
3159 	    {
3160 	      exprNodeList_elements (args, e)
3161 		{
3162 		  if (exprNode_isDefined (e))
3163 		    {
3164 		      sRef s = exprNode_getSref (e);
3165 
3166 		      if (sRef_isObserver (s)
3167 			  && ctype_isMutable (sRef_getType (s)))
3168 			{
3169 			  if (optgenerror
3170 			      (FLG_MODOBSERVERUNCON,
3171 			       message
3172 			       ("Call to unconstrained function %s may modify observer%q: %s",
3173 				exprNode_unparse (f),
3174 				sRef_unparsePreOpt (s), exprNode_unparse (e)),
3175 			       exprNode_loc (e)))
3176 			    {
3177 			      sRef_showExpInfo (s);
3178 			    }
3179 			}
3180 		    }
3181 		} end_exprNodeList_elements;
3182 	    }
3183 	}
3184     }
3185 
3186   checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3187 
3188   ret->uses = sRefSet_union (ret->uses, f->uses);
3189   ret->sets = sRefSet_union (ret->sets, f->sets);
3190   ret->msets = sRefSet_union (ret->msets, f->msets);
3191 
3192   if (freshMods)
3193     {
3194       /*
3195       ** Spurious errors reported, because splint can't tell
3196       ** mods must be fresh if freshMods is true.
3197       */
3198 
3199       /*@i@*/ sRefSet_free (mods);
3200     }
3201 
3202   setCodePoint ();
3203 }
3204 
checkGlobUse(uentry glob,bool isCall,exprNode e)3205 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3206 {
3207   if (uentry_isVar (glob))
3208     {
3209       if (context_inFunctionLike ())
3210 	{
3211 	  sRef sr = uentry_getSref (glob);
3212 
3213 	  context_usedGlobal (sr);
3214 
3215 	  if (context_checkGlobUse (glob))
3216 	    {
3217 	      if (!context_globAccess (sr))
3218 		{
3219 		  if (isCall)
3220 		    {
3221 		      voptgenerror
3222 			(FLG_GLOBALS,
3223 			 message ("Called procedure %s may access %s %q",
3224 				  exprNode_unparse (e),
3225 				  sRef_unparseScope (sr),
3226 				  uentry_getName (glob)),
3227 			 e->loc);
3228 		    }
3229 		  else
3230 		    {
3231 		      voptgenerror
3232 			(FLG_GLOBALS,
3233 			 message ("Undocumented use of %s %s",
3234 				  sRef_unparseScope (sr),
3235 				  exprNode_unparse (e)),
3236 			 e->loc);
3237 		    }
3238 		}
3239 	    }
3240 	}
3241     }
3242   else
3243     {
3244       llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3245     }
3246 }
3247 
3248 static void
reflectEnsuresClause(exprNode ret,uentry le,exprNode f,exprNodeList args)3249 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3250 {
3251   DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3252 	    exprNode_unparse (f), exprNodeList_unparse (args),
3253 	    uentry_unparseFull (le),
3254 	    stateClauseList_unparse (uentry_getStateClauseList (le))));
3255 
3256   if (uentry_isValid (le) && uentry_isFunction (le))
3257     {
3258       stateClauseList sclauses = uentry_getStateClauseList (le);
3259 
3260       if (stateClauseList_isDefined (sclauses))
3261 	{
3262 	  DPRINTF (("Reflect ensures: %s / %s / %s",
3263 		    uentry_unparse (le),
3264 		    exprNode_unparse (f), exprNodeList_unparse (args)));
3265 
3266 	  stateClauseList_elements (sclauses, cl)
3267 	    {
3268 	      if (stateClause_hasEnsures (cl))
3269 		{
3270 		  /* Same in usymtab.c:1904 */
3271 		  if (stateClause_setsMetaState (cl))
3272 		    {
3273 		      qual q = stateClause_getMetaQual (cl);
3274 		      annotationInfo ainfo = qual_getAnnotationInfo (q);
3275 		      metaStateInfo minfo = annotationInfo_getState (ainfo);
3276 		      cstring key = metaStateInfo_getName (minfo);
3277 		      int mvalue = annotationInfo_getValue (ainfo);
3278 
3279 		      sRefSet osrs = sRefSet_undefined;
3280 		      sRefSet srs;
3281 
3282 		      if (stateClause_isGlobal (cl))
3283 			{
3284 			  srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3285 			  osrs = srs;
3286 			}
3287 		      else
3288 			{
3289 			  srs = stateClause_getRefs (cl);
3290 			}
3291 
3292 		      DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3293 
3294 
3295 		      DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3296 
3297 		      sRefSet_elements (srs, sel)
3298 			{
3299 			  sRef s;
3300 
3301 			  if (sRef_isResult (sRef_getRootBase (sel)))
3302 			    {
3303 			      s = exprNode_getSref (ret);
3304 			    }
3305 			  else
3306 			    {
3307 			      s = sRef_fixBaseParam (sel, args);
3308 			    }
3309 
3310 			  DPRINTF (("Reflecting state clause on: %s / %s",
3311 				    sRef_unparse (sel), sRef_unparse (s)));
3312 
3313 			  sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3314 			} end_sRefSet_elements;
3315 
3316 		      sRefSet_free (osrs);
3317 		    }
3318 		  else
3319 		    {
3320 		      sRefSet srs = stateClause_getRefs (cl);
3321 		      sRefModVal modf = stateClause_getEnsuresFunction (cl);
3322 		      int eparam = stateClause_getStateParameter (cl);
3323 
3324 		      llassert (modf != NULL);
3325 
3326 		      DPRINTF (("Reflect after clause: %s / %s",
3327 				stateClause_unparse (cl),
3328 				sRefSet_unparse (srs)));
3329 
3330 		      sRefSet_elements (srs, sel)
3331 			{
3332 			  sRef s;
3333 
3334 			  DPRINTF (("elements: %s", sRef_unparse (sel)));
3335 			  DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3336 
3337 			  if (sRef_isResult (sRef_getRootBase (sel)))
3338 			    {
3339 			      DPRINTF (("Fix base: %s / %s",
3340 					sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3341 			      s = sRef_fixBase (sel, exprNode_getSref (ret));
3342 			      DPRINTF (("==> %s", sRef_unparseFull (s)));
3343 			    }
3344 			  else
3345 			    {
3346 			      s = sRef_fixBaseParam (sel, args);
3347 			    }
3348 
3349 			  DPRINTF (("elements: %s", sRef_unparse (s)));
3350 			  DPRINTF (("elements: %s", sRef_unparseFull (s)));
3351 
3352 			  DPRINTF (("Reflecting state clause on: %s / %s",
3353 				    sRef_unparseFull (sel), sRef_unparseFull (s)));
3354 
3355 			  /* evans 2001-08-24 - added aliasSetCompleteParam */
3356 			  sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3357 
3358 			  DPRINTF (("After reflecting state clause on: %s / %s",
3359 				    sRef_unparseFull (sel), sRef_unparseFull (s)));
3360 			} end_sRefSet_elements;
3361 		    }
3362 		}
3363 	    } end_stateClauseList_elements ;
3364 	}
3365 
3366       DPRINTF (("Here: %s / %s",
3367 		uentry_unparseFull (le),
3368 		bool_unparse (uentry_hasMetaStateEnsures (le))));
3369 
3370       if (uentry_hasMetaStateEnsures (le))
3371 	{
3372 	  fileloc loc = exprNode_loc (f);
3373 
3374 	  metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3375 
3376 	  metaStateConstraintList_elements (mscl, msc)
3377 	    {
3378 	      metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3379 	      metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3380 	      metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3381 	      cstring key = metaStateInfo_getName (msinfo);
3382 	      sRef mlsr = metaStateSpecifier_getSref (msspec);
3383 	      sRef s;
3384 	      sRef lastref = sRef_undefined;
3385 	      stateValue sval = stateValue_undefined;
3386 
3387 	      DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3388 			metaStateConstraint_unparse (msc)));
3389 	      DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3390 
3391 	      if (sRef_isResult (sRef_getRootBase (mlsr)))
3392 		{
3393 		  s = exprNode_getSref (ret);
3394 		}
3395 	      else
3396 		{
3397 		  s = sRef_fixBaseParam (mlsr, args);
3398 		}
3399 
3400 	      DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3401 
3402 	      while (metaStateExpression_isDefined (msexpr))
3403 		{
3404 		  metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3405 		  metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3406 		  sRef msr, fs;
3407 
3408 		  DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3409 
3410 		  if (metaStateExpression_isMerge (msexpr))
3411 		    {
3412 		      msexpr = metaStateExpression_getRest (msexpr);
3413 		    }
3414 		  else
3415 		    {
3416 		      msexpr = metaStateExpression_undefined;
3417 		    }
3418 
3419 		  if (metaStateInfo_isDefined (msi))
3420 		    {
3421 		      /* Must match lhs state */
3422 		      llassert (metaStateInfo_equal (msinfo, msi));
3423 		    }
3424 
3425 		  if (metaStateSpecifier_isElipsis (ms))
3426 		    {
3427 		      /*
3428 		      ** For elipsis, we need to merge all the relevant elipsis parameters
3429 		      **
3430 		      */
3431 
3432 		      uentryList params = uentry_getParams (le);
3433 		      int paramno = uentryList_size (params) - 1;
3434 
3435 		      if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3436 			{
3437 			  voptgenerror
3438 			    (FLG_TYPE,
3439 			     message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3440 				      uentry_getName (le)),
3441 			     uentry_whereLast (le));
3442 			  /*@innerbreak@*/ break;
3443 			}
3444 
3445 		      while (paramno < exprNodeList_size (args))
3446 			{
3447 			  exprNode arg = exprNodeList_getN (args, paramno);
3448 			  fs = exprNode_getSref (arg);
3449 			  DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3450 
3451 			  /* cut and pasted... gack*/
3452 			  if (stateValue_isDefined (sval))
3453 			    {
3454 			      /* Use combination table to merge old state value with new one: */
3455 			      stateValue tval = sRef_getMetaStateValue (fs, key);
3456 
3457 			      if (stateValue_isDefined (tval))
3458 				{
3459 				  stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3460 				  cstring msg = cstring_undefined;
3461 				  int nval = stateCombinationTable_lookup (sctable,
3462 									   stateValue_getValue (sval),
3463 									   stateValue_getValue (tval),
3464 									   &msg);
3465 				  DPRINTF (("Combining: %s + %s -> %d",
3466 					    stateValue_unparseValue (sval, msinfo),
3467 					    stateValue_unparseValue (tval, msinfo),
3468 					    nval));
3469 
3470 				  if (nval == stateValue_error)
3471 				    {
3472 				      if (optgenerror
3473 					  (FLG_STATEMERGE,
3474 					   message
3475 					   ("Attributes merged in ensures clause in states that "
3476 					    "cannot be combined (%q is %q, %q is %q)%q",
3477 					    sRef_unparse (lastref),
3478 					    stateValue_unparseValue (sval, msinfo),
3479 					    sRef_unparse (fs),
3480 					    stateValue_unparseValue (tval, msinfo),
3481 					    cstring_isDefined (msg) ?
3482 					    message (": %s", msg) : cstring_undefined),
3483 					   exprNode_loc (f)))
3484 					{
3485 					  sRef_showMetaStateInfo (fs, key);
3486 					}
3487 				    }
3488 
3489 				  stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3490 				  loc = exprNode_loc (arg);
3491 				}
3492 			      else
3493 				{
3494 				  DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3495 				}
3496 			    }
3497 			  else
3498 			    {
3499 			      sval = sRef_getMetaStateValue (fs, key);
3500 			    }
3501 
3502 			  lastref = fs;
3503 
3504 			  if (stateValue_isError (sval))
3505 			    {
3506 			      /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3507 			    }
3508 
3509 
3510 			  paramno++;
3511 			}
3512 		    }
3513 		  else
3514 		    {
3515 		      msr = metaStateSpecifier_getSref (ms);
3516 
3517 
3518 		      llassert (sRef_isParam (sRef_getRootBase (msr)));
3519 		      fs = sRef_fixBaseParam (msr, args);
3520 
3521 		      if (stateValue_isDefined (sval))
3522 			{
3523 			  /* Use combination table to merge old state value with new one: */
3524 			  stateValue tval = sRef_getMetaStateValue (fs, key);
3525 
3526 			  if (stateValue_isDefined (tval))
3527 			    {
3528 			      stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3529 			      cstring msg = cstring_undefined;
3530 			      int nval = stateCombinationTable_lookup (sctable,
3531 								       stateValue_getValue (sval),
3532 								       stateValue_getValue (tval),
3533 								       &msg);
3534 			      DPRINTF (("Combining: %s + %s -> %d",
3535 					stateValue_unparseValue (sval, msinfo),
3536 					stateValue_unparseValue (tval, msinfo),
3537 					nval));
3538 
3539 			      if (nval == stateValue_error)
3540 				{
3541 				  if (optgenerror
3542 				      (FLG_STATEMERGE,
3543 				       message
3544 				       ("Attributes merged in ensures clause in states that "
3545 					"cannot be combined (%q is %q, %q is %q)%q",
3546 					sRef_unparse (lastref),
3547 					stateValue_unparseValue (sval, msinfo),
3548 					sRef_unparse (fs),
3549 					stateValue_unparseValue (tval, msinfo),
3550  					cstring_isDefined (msg)
3551  					? message (": %s", msg) : cstring_undefined),
3552 				       exprNode_loc (f)))
3553 				    {
3554 				      sRef_showMetaStateInfo (fs, key);
3555 				    }
3556 				}
3557 
3558 			      stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3559 			    }
3560 			  else
3561 			    {
3562 			      DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3563 			    }
3564 			}
3565 		      else
3566 			{
3567 			  sval = sRef_getMetaStateValue (fs, key);
3568 			}
3569 
3570 		      lastref = fs;
3571 
3572 		      if (stateValue_isError (sval))
3573 			{
3574 			  /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3575 			}
3576 		    }
3577 		}
3578 
3579 	      DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3580 
3581 	      if (stateValue_isDefined (sval))
3582 		{
3583 		  sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3584 		}
3585 	      else
3586 		{
3587 		  DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3588 		}
3589 	    } end_metaStateConstraintList_elements ;
3590 
3591 	  metaStateConstraintList_free (mscl);
3592 	}
3593     }
3594 }
3595 
3596 static void
checkRequiresClause(uentry le,exprNode f,exprNodeList args)3597 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3598 {
3599   DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3600 	    exprNode_unparse (f), exprNodeList_unparse (args),
3601 	    uentry_unparseFull (le),
3602 	    stateClauseList_unparse (uentry_getStateClauseList (le))));
3603 
3604   if (uentry_isValid (le) && uentry_isFunction (le))
3605     {
3606       stateClauseList sclauses = uentry_getStateClauseList (le);
3607 
3608       if (stateClauseList_isDefined (sclauses))
3609 	{
3610 	  DPRINTF (("Check requires: %s / %s / %s",
3611 		    uentry_unparse (le),
3612 		    exprNode_unparse (f), exprNodeList_unparse (args)));
3613 
3614 	  stateClauseList_elements (sclauses, cl)
3615 	    {
3616 	      DPRINTF (("Check clause: %s / %s",
3617 			stateClause_unparse (cl),
3618 			bool_unparse (stateClause_hasRequires (cl))));
3619 
3620 	      if (stateClause_hasRequires (cl))
3621 		{
3622 		  sRefSet osrs = sRefSet_undefined;
3623 		  sRefSet srs;
3624 
3625 		  if (stateClause_isGlobal (cl))
3626 		    {
3627 		      srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3628 		      osrs = srs;
3629 		    }
3630 		  else
3631 		    {
3632 		      srs = stateClause_getRefs (cl);
3633 		    }
3634 
3635 		  DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3636 
3637 		  if (stateClause_setsMetaState (cl))
3638 		    {
3639 		      qual q = stateClause_getMetaQual (cl);
3640 		      annotationInfo ainfo = qual_getAnnotationInfo (q);
3641 		      metaStateInfo minfo = annotationInfo_getState (ainfo);
3642 		      cstring key = metaStateInfo_getName (minfo);
3643 		      int mvalue = annotationInfo_getValue (ainfo);
3644 
3645 		      DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3646 
3647 		      sRefSet_elements (srs, sel)
3648 			{
3649 			  sRef s = sRef_fixBaseParam (sel, args);
3650 
3651 			  if (sRef_isResult (sRef_getRootBase (sel)))
3652 			    {
3653 			      BADBRANCH;
3654 			    }
3655 			  else
3656 			    {
3657 			      DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3658 					sRef_unparseFull (sel), sRef_unparseFull (s),
3659 					key, mvalue));
3660 
3661 			      if (!sRef_checkMetaStateValue (s, key, mvalue))
3662 				{
3663 				  DPRINTF (("HERE: %s", sRef_unparse (s)));
3664 				  if (optgenerror
3665 				      (FLG_STATETRANSFER,
3666 				       message
3667 				       ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3668 					uentry_getName (le),
3669 					sRef_isGlobalMarker (s)
3670 					   ? message ("")
3671 					   : message (" by %q", sRef_unparse (s)),
3672 					stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3673 								 minfo),
3674 					stateClause_unparse (cl)),
3675 				       exprNode_loc (f)))
3676 				    {
3677 				      sRef_showAliasInfo (s);
3678 				    }
3679 				  else
3680 				    {
3681 				      DPRINTF (("Error supressed!"));
3682 				      DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3683 				      DPRINTF (("Context supress: %s",
3684 						bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3685 				    }
3686 				}
3687 			    }
3688 			} end_sRefSet_elements;
3689 		    }
3690 		  else
3691 		    {
3692 		      sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3693 		      int eparam = stateClause_getStateParameter (cl);
3694 
3695 		      DPRINTF (("Reflect after clause: %s / %s",
3696 				stateClause_unparse (cl),
3697 				sRefSet_unparse (srs)));
3698 
3699 		      llassert (modf != NULL);
3700 
3701 		      sRefSet_elements (srs, sel)
3702 			{
3703 			  sRef s;
3704 
3705 			  DPRINTF (("elements: %s", sRef_unparse (sel)));
3706 			  DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3707 
3708 			  s = sRef_fixBaseParam (sel, args);
3709 
3710 			  DPRINTF (("elements: %s", sRef_unparse (s)));
3711 			  DPRINTF (("elements: %s", sRef_unparseFull (s)));
3712 
3713 			  if (sRef_isResult (sRef_getRootBase (sel)))
3714 			    {
3715 			      ; /* what do we do about results? */
3716 			    }
3717 			  else
3718 			    {
3719 			      DPRINTF (("Reflecting state clause on: %s / %s",
3720 					sRef_unparse (sel), sRef_unparse (s)));
3721 
3722 			      modf (s, eparam, exprNode_loc (f));
3723 			    }
3724 			} end_sRefSet_elements;
3725 		    }
3726 
3727 		  sRefSet_free (osrs);
3728 		}
3729 	    } end_stateClauseList_elements ;
3730 	}
3731     }
3732 }
3733 
3734 static /*@only@*/ exprNode
functionCallSafe(exprNode f,ctype t,exprNodeList args)3735 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3736 		  ctype t, /*@keep@*/ exprNodeList args)
3737 {
3738   /* requires f is a non-error exprNode, with type function */
3739   cstring fname = exprNode_unparse (f);
3740   uentry le = exprNode_getUentry (f);
3741   exprNode ret = exprNode_createPartialCopy (f);
3742   int special;
3743 
3744   setCodePoint ();
3745 
3746   DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3747 
3748   ret->typ = ctype_getReturnType (t);
3749   ret->kind = XPR_CALL;
3750 
3751   ret->edata = exprData_makeCall (f, args);
3752 
3753   /*
3754   ** Order of these steps is very important!
3755   **
3756   ** Must check for argument dependencies before messing up uses and sets.
3757   */
3758 
3759   if (context_getFlag (FLG_EVALORDER))
3760     {
3761       exprNodeList_elements (args, current)
3762 	{
3763 	  if (exprNode_isDefined (current))
3764 	    {
3765 	      exprNode_addUse (current, current->sref);
3766 	    }
3767 	} end_exprNodeList_elements;
3768 
3769       if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3770 	{
3771 	  checkSequencing (f, args);
3772 	}
3773 
3774       exprNodeList_elements (args, current)
3775 	{
3776 	  if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3777 	    {
3778 	      exprNode_addUse (ret, sRef_makeDerived (current->sref));
3779 	    }
3780 	} end_exprNodeList_elements ;
3781     }
3782 
3783   special = checkArgs (le, f, t, args, ret);
3784   checkGlobMods (f, le, args, ret, special);
3785   checkRequiresClause (le, f, args);
3786   setCodePoint ();
3787 
3788   if (uentry_isValid (le)
3789       && (uentry_isFunction (le)
3790           || (uentry_isVariable (le)
3791 	      && ctype_isFunction (uentry_getType (le)))))
3792     {
3793       exitkind exk = uentry_getExitCode (le);
3794 
3795       /* f->typ is already set to the return type */
3796 
3797       DPRINTF (("Function: %s", uentry_unparseFull (le)));
3798       ret->sref = uentry_returnedRef (le, args, exprNode_loc (f));
3799       DPRINTF (("Returned: %s / %s",
3800 		uentry_unparseFull (le),
3801 		sRef_unparseFull (ret->sref)));
3802 
3803       if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3804 	{
3805 	  qual nullPred = uentry_nullPred (le);
3806 
3807 	  if (qual_isTrueNull (nullPred))
3808 	    {
3809 	      exprNode arg = exprNodeList_head (args);
3810 
3811 	      if (exprNode_isDefined (arg))
3812 		{
3813 		  ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3814 		}
3815 	    }
3816 	  else if (qual_isFalseNull (nullPred))
3817 	    {
3818 	      exprNode arg = exprNodeList_head (args);
3819 
3820 	      if (exprNode_isDefined (arg))
3821 		{
3822 		  ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3823 		}
3824 	    }
3825 	  else
3826 	    {
3827 	      llassert (qual_isUnknown (nullPred));
3828 	    }
3829 	}
3830 
3831       if (exitkind_isConditionalExit (exk))
3832 	{
3833 	  /*
3834 	  ** True exit is:
3835 	  **    if (arg0) then { exit! } else { ; }
3836 	  ** False exit is:
3837 	  **    if (arg0) then { ; } else { exit! }
3838 	  */
3839 
3840 	  exprNode firstArg;
3841 
3842 	  llassert (!exprNodeList_isEmpty (args));
3843 	  firstArg = exprNodeList_head (args);
3844 
3845 	  if (exprNode_isDefined (firstArg)
3846 	      && !guardSet_isEmpty (firstArg->guards))
3847 	    {
3848 	      usymtab_trueBranch (guardSet_undefined);
3849 	      usymtab_altBranch (guardSet_undefined);
3850 
3851 	      if (exitkind_isTrueExit (exk))
3852 		{
3853 		  usymtab_popBranches (firstArg,
3854 				       exprNode_makeMustExit (),
3855 				       exprNode_undefined,
3856 				       TRUE, TRUEEXITCLAUSE);
3857 		}
3858 	      else
3859 		{
3860 		  usymtab_popBranches (firstArg,
3861 				       exprNode_undefined,
3862 				       exprNode_makeMustExit (),
3863 				       TRUE, FALSEEXITCLAUSE);
3864 		}
3865 	    }
3866 
3867 	  ret->exitCode = XK_MAYEXIT;
3868 	}
3869       else if (exitkind_mustExit (exk))
3870 	{
3871 	  ret->exitCode = XK_MUSTEXIT;
3872 	}
3873       else if (exitkind_couldExit (exk))
3874 	{
3875 	  ret->exitCode = XK_MAYEXIT;
3876 	}
3877       else
3878 	{
3879 	  ;
3880 	}
3881 
3882       if (cstring_equalLit (fname, "exit"))
3883 	{
3884 	  if (exprNodeList_size (args) == 1)
3885 	    {
3886 	      exprNode arg = exprNodeList_head (args);
3887 
3888 	      if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3889 		{
3890 		  long int val = multiVal_forceInt (exprNode_getValue (arg));
3891 
3892 		  if (val != 0)
3893 		    {
3894 		      voptgenerror
3895 			(FLG_EXITARG,
3896 			 message
3897 			 ("Argument to exit has implementation defined behavior: %s",
3898 			  exprNode_unparse (arg)),
3899 			 exprNode_loc (arg));
3900 		    }
3901 		}
3902 	    }
3903 	}
3904     }
3905   else
3906     {
3907       ret->sref = sRef_undefined;
3908       exprNode_checkSetAny (ret, uentry_rawName (le));
3909     }
3910 
3911   DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3912   DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3913   reflectEnsuresClause (ret, le, f, args);
3914   setCodePoint ();
3915 
3916   DPRINTF (("Here: %s", sRef_unparseFull (ret->sref)));
3917   return (ret);
3918 }
3919 
3920 /*
3921 ** this is yucky!  should keep the uentry as part of exprNode!
3922 */
3923 
exprNode_getUentry(exprNode e)3924 uentry exprNode_getUentry (exprNode e)
3925 {
3926   if (exprNode_isError (e))
3927     {
3928       return uentry_undefined;
3929     }
3930   else
3931     {
3932       cstring s = exprNode_rootVarName (e);
3933       uentry ue = usymtab_lookupSafe (s);
3934 
3935       return ue;
3936     }
3937 }
3938 
3939 /*
3940 ** Returns true iff e1 and e2 are both exactly the same storage
3941 ** (conservative).
3942 */
3943 
exprNode_sameStorage(exprNode e1,exprNode e2)3944 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3945 {
3946   sRef s1 = exprNode_getSref (e1);
3947   sRef s2 = exprNode_getSref (e2);
3948 
3949   return (sRef_realSame (s1, s2));
3950 }
3951 
3952 exprNode
exprNode_makeInitBlock(lltok brace,exprNodeList inits)3953 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3954 {
3955   exprNode ret = exprNode_createPlain (ctype_unknown);
3956 
3957   ret->kind = XPR_INITBLOCK;
3958   ret->edata = exprData_makeCall (exprNode_undefined, inits);
3959   ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3960 
3961   return (ret);
3962 }
3963 
3964 exprNode
exprNode_functionCall(exprNode f,exprNodeList args)3965 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3966 {
3967   ctype t;
3968 
3969 # ifdef DEBUGSPLINT
3970   usymtab_checkAllValid ();
3971 # endif
3972 
3973   if (exprNode_isUndefined (f))
3974     {
3975       exprNode_free (f);
3976       exprNodeList_free (args);
3977       return exprNode_undefined;
3978     }
3979 
3980   t = exprNode_getType (f);
3981 
3982   if (sRef_isLocalVar (f->sref))
3983     {
3984       exprNode_checkUse (f, f->sref, f->loc);
3985 
3986       if (sRef_possiblyNull (f->sref))
3987         {
3988           if (!usymtab_isGuarded (f->sref))
3989             {
3990               if (optgenerror (FLG_NULLDEREF,
3991 			       message ("Function call using %s pointer %q",
3992 					sRef_nullMessage (f->sref),
3993 					sRef_unparse (f->sref)),
3994 			       f->loc))
3995 		{
3996 		  sRef_showNullInfo (f->sref);
3997 		  sRef_setNullError (f->sref);
3998 		}
3999             }
4000         }
4001     }
4002 
4003   setCodePoint ();
4004 
4005   if (ctype_isRealFunction (t))
4006     {
4007       exprNode ret = functionCallSafe (f, t, args);
4008       setCodePoint ();
4009       return ret;
4010     }
4011   else if (ctype_isUnknown (t))
4012     {
4013       exprNode ret = exprNode_createPartialCopy (f);
4014       cstring tstring;
4015 
4016       setCodePoint ();
4017 
4018       ret->typ = t;
4019       exprNodeList_elements (args, current)
4020         {
4021           if (exprNode_isDefined (current))
4022             {
4023               exprNode_checkUse (ret, current->sref, ret->loc);
4024 
4025 	      /*
4026 	      ** also, anything derivable from current->sref may be used
4027 	      */
4028 
4029 	      exprNode_addUse (ret, sRef_makeDerived (current->sref));
4030               exprNode_mergeUSs (ret, current);
4031             }
4032         } end_exprNodeList_elements;
4033 
4034       ret->edata = exprData_makeCall (f, args);
4035       ret->kind = XPR_CALL;
4036 
4037       tstring = cstring_copy (exprNode_unparse (f));
4038 
4039       cstring_markOwned (tstring);
4040       exprNode_checkSetAny (ret, tstring);
4041 
4042       return (ret);
4043     }
4044   else
4045     {
4046       voptgenerror (FLG_TYPE,
4047 		    message ("Call to non-function (type %t): %s", t,
4048 			     exprNode_unparse (f)),
4049 		    f->loc);
4050       exprNode_free (f);
4051       exprNodeList_free (args);
4052 
4053       return (exprNode_makeError ());
4054     }
4055 }
4056 
4057 static exprNode
exprNode_fieldAccessAux(exprNode s,fileloc loc,cstring f)4058 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4059 			 /*@only@*/ cstring f)
4060 {
4061   exprNode ret = exprNode_createPartialCopy (s);
4062 
4063   ret->kind = XPR_FACCESS;
4064 
4065   if (exprNode_isError (s))
4066     {
4067       ret->edata = exprData_makeField (s, f);
4068       return ret;
4069     }
4070   else
4071     {
4072       ctype t = exprNode_getType (s);
4073       ctype tr = ctype_realType (t);
4074 
4075       checkMacroParen (s);
4076 
4077       ret->edata = exprData_makeField (s, f);
4078 
4079       if (ctype_isStructorUnion (tr))
4080         {
4081           uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4082 
4083           if (uentry_isUndefined (tf))
4084             {
4085               voptgenerror (FLG_TYPE,
4086 			    message ("Access non-existent field %s of %t: %s", f, t,
4087 				     exprNode_unparse (ret)),
4088 			    loc);
4089 	      /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4090               return (ret);
4091             }
4092           else
4093             {
4094 	      uentry_setUsed (tf, exprNode_loc (ret));
4095 
4096               ret->typ = uentry_getType (tf);
4097               checkSafeUse (ret, s->sref);
4098 
4099               ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4100 	      /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4101               return (ret);
4102             }
4103         }
4104       else /* isStructorUnion */
4105         {
4106           if (ctype_isRealAbstract (tr))
4107             {
4108               voptgenerror
4109 		(FLG_ABSTRACT,
4110 		 message ("Access field of abstract type (%t): %s.%s",
4111 			  t, exprNode_unparse (s), f),
4112 		 loc);
4113               ret->typ = ctype_unknown;
4114             }
4115           else
4116             {
4117               if (ctype_isKnown (tr))
4118 		{
4119 		  voptgenerror
4120 		    (FLG_TYPE,
4121 		     message
4122 		     ("Access field of non-struct or union (%t): %s.%s",
4123 		      t, exprNode_unparse (s), f),
4124 		     loc);
4125 
4126 		  ret->typ = ctype_unknown;
4127 		}
4128               else
4129 		{
4130 		  cstring sn = cstring_copy (f);
4131 
4132 		  checkSafeUse (ret, s->sref);
4133 		  cstring_markOwned (sn);
4134 		  ret->sref = sRef_makeField (s->sref, sn);
4135 		  return (ret);
4136 		}
4137             }
4138 
4139           return (ret);
4140         }
4141     }
4142   BADEXIT;
4143 }
4144 
4145 exprNode
exprNode_fieldAccess(exprNode s,lltok dot,cstring f)4146 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4147 		      /*@only@*/ cstring f)
4148 {
4149   exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4150   lltok_free (dot);
4151   return res;
4152 }
4153 
4154 exprNode
exprNode_addParens(lltok lpar,exprNode e)4155 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4156 {
4157   exprNode ret = exprNode_createPartialCopy (e);
4158 
4159   ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4160   ret->kind = XPR_PARENS;
4161   ret->edata = exprData_makeUop (e, lpar);
4162 
4163   if (!exprNode_isError (e))
4164     {
4165       ret->exitCode = e->exitCode;
4166       ret->canBreak = e->canBreak;
4167       ret->mustBreak = e->mustBreak;
4168       ret->isJumpPoint = e->isJumpPoint;
4169       ret->sref = e->sref;
4170     }
4171 
4172   return ret;
4173 }
4174 
4175 static exprNode
exprNode_arrowAccessAux(exprNode s,fileloc loc,cstring f)4176 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4177 			 /*@only@*/ cstring f)
4178 {
4179   exprNode ret = exprNode_createPartialCopy (s);
4180 
4181   ret->edata = exprData_makeField (s, f);
4182   ret->kind = XPR_ARROW;
4183 
4184   if (exprNode_isError (s))
4185     {
4186       return (ret);
4187     }
4188   else
4189     {
4190       ctype t = exprNode_getType (s);
4191       ctype tr = ctype_realType (t);
4192 
4193       checkMacroParen (s);
4194 
4195       (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4196 
4197       if (ctype_isRealPointer (tr))
4198 	{
4199 	  ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4200 
4201 	  if (ctype_isStructorUnion (b))
4202 	    {
4203 	      uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4204 
4205 	      if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4206 		{
4207 		  if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4208 		    {
4209 		      if (optgenerror
4210 			  (FLG_NULLDEREF,
4211 			   message ("Arrow access from %s pointer%q: %s",
4212 				    sRef_nullMessage (s->sref),
4213 				    sRef_unparsePreOpt (s->sref),
4214 				    exprNode_unparse (ret)),
4215 			   loc))
4216 			{
4217 			  sRef_showNullInfo (s->sref);
4218 			  sRef_setNullError (s->sref);
4219 			}
4220 		    }
4221 		}
4222 
4223 	      if (uentry_isUndefined (fentry))
4224 		{
4225 		  voptgenerror
4226 		    (FLG_TYPE,
4227 		     message ("Access non-existent field %s of %t: %s",
4228 			      f, t, exprNode_unparse (ret)),
4229 		     loc);
4230 		  ret->typ = ctype_unknown;
4231 		  return (ret);
4232 		}
4233 	      else
4234 		{
4235 		  /*
4236 		  ** was safeUse: shouldn't be safe!
4237 		  **
4238 		  ** to do rec->field
4239 		  ** rec must be defined,
4240 		  ** *rec must be allocated
4241 		  ** rec->field need only be defined it if is an rvalue
4242 		  */
4243 
4244 		  uentry_setUsed (fentry, exprNode_loc (ret));
4245 		  ret->typ = uentry_getType (fentry);
4246 
4247 		  exprNode_checkUse (ret, s->sref, s->loc);
4248 
4249 		  /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4250 		  ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4251 		  return (ret);
4252 		}
4253 	    }
4254 	  else /* Pointer to something that is not a struct or union*/
4255 	    {
4256 	      if (ctype_isRealAbstract (tr))
4257 		{
4258 		  ctype xrt = ctype_forceRealType (tr);
4259 
4260 		  voptgenerror
4261 		    (FLG_ABSTRACT,
4262 		     message ("Arrow access field of abstract type (%t): %s->%s",
4263 			      t, exprNode_unparse (s), f),
4264 		     loc);
4265 
4266 		  /*
4267 		  ** Set the state correctly, as if the abstraction is broken.
4268 		  */
4269 
4270 		  if (ctype_isRealPointer (xrt) &&
4271 		      (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4272 		       ctype_isStructorUnion (b)))
4273 		    {
4274 		      uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4275 		      ret->typ = uentry_getType (fentry);
4276 		      ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4277 		    }
4278 		  else
4279 		    {
4280 		      ret->typ = ctype_unknown;
4281 		      ret->sref = sRef_undefined;
4282 		    }
4283 		}
4284 	      else /* not a struct, union or abstract */
4285 		{
4286 		  if (ctype_isUnknown (tr)) {
4287 		    cstring sn = cstring_copy (f);
4288 
4289 		    DPRINTF (("Here: %s", exprNode_unparse (s)));
4290 
4291 		    exprNode_checkUse (ret, s->sref, s->loc);
4292 		    exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4293 
4294 		    cstring_markOwned (sn);
4295 		    ret->sref = sRef_makeArrow (s->sref, sn);
4296 
4297 		    ret->kind = XPR_ARROW;
4298 		    return (ret);
4299 		  } else {
4300 		    voptgenerror
4301 		      (FLG_TYPE,
4302 		       message ("Arrow access field of non-struct or union "
4303 				"pointer (%t): %s->%s",
4304 				t, exprNode_unparse (s), f),
4305 		       loc);
4306 
4307 		    ret->typ = ctype_unknown;
4308 		    ret->sref = sRef_undefined;
4309 		  }
4310 		}
4311 	    }
4312 	}
4313       else /* its not a pointer */
4314 	{
4315 	  if (!ctype_isUnknown (tr))
4316 	    {
4317 	      voptgenerror
4318 		(FLG_TYPE,
4319 		 message ("Arrow access of non-pointer (%t): %s->%s",
4320 			  t, exprNode_unparse (s), f),
4321 		 loc);
4322 
4323 	      ret->typ = ctype_unknown;
4324 	      ret->sref = sRef_undefined;
4325 	    }
4326 	  else
4327 	    {
4328 	      cstring sn = cstring_copy (f);
4329 
4330 	      DPRINTF (("Here: %s", exprNode_unparse (s)));
4331 
4332 	      exprNode_checkUse (ret, s->sref, s->loc);
4333 	      exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4334 
4335 	      cstring_markOwned (sn);
4336 	      ret->sref = sRef_makeArrow (s->sref, sn);
4337 
4338 	      ret->kind = XPR_ARROW;
4339 	      return (ret);
4340 	    }
4341 	}
4342 
4343       return (ret);
4344     }
4345   BADEXIT;
4346 }
4347 
4348 exprNode
exprNode_arrowAccess(exprNode s,lltok arrow,cstring f)4349 exprNode_arrowAccess (/*@only@*/ exprNode s,
4350 		      /*@only@*/ lltok arrow,
4351 		      /*@only@*/ cstring f)
4352 {
4353   exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4354   lltok_free (arrow);
4355   return res;
4356 }
4357 
4358 /*
4359 ** only postOp's in C: i++ and i--
4360 */
4361 
4362 exprNode
exprNode_postOp(exprNode e,lltok op)4363 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4364 {
4365   /* check modification also */
4366   /* cstring opname = lltok_unparse (op);*/
4367   ctype t;
4368   exprNode ret = exprNode_createPartialCopy (e);
4369 
4370   ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4371   ret->kind = XPR_POSTOP;
4372   ret->edata = exprData_makeUop (e, op);
4373 
4374   if (!exprNode_isDefined (e))
4375     {
4376       return ret;
4377     }
4378 
4379   checkMacroParen (e);
4380 
4381   exprNode_checkUse (ret, e->sref, e->loc);
4382   exprNode_checkSet (ret, e->sref);
4383 
4384   t = exprNode_getType (e);
4385 
4386   if (sRef_isUnsafe (e->sref))
4387     {
4388       voptgenerror (FLG_MACROPARAMS,
4389 		    message ("Operand of %s is macro parameter (non-functional): %s%s",
4390 			     lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4391 		    e->loc);
4392       sRef_makeSafe (e->sref);
4393       sRef_makeSafe (ret->sref);
4394     }
4395 
4396   if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4397     {
4398       ret->typ = e->typ;
4399     }
4400   else
4401     {
4402       if (ctype_isRealAbstract (t))
4403         {
4404 	  if (ctype_isRealNumAbstract (t)) {
4405 	    ; /* Allow operations on numabstract types */
4406 	  } else {
4407 	    voptgenerror
4408 	      (FLG_ABSTRACT,
4409 	       message ("Operand of %s is abstract type (%t): %s",
4410 			lltok_unparse (op), t, exprNode_unparse (e)),
4411 	       e->loc);
4412 	  }
4413         }
4414       else
4415         {
4416           voptgenerror
4417 	    (FLG_TYPE,
4418 	     message ("Operand of %s is non-numeric (%t): %s",
4419 		      lltok_unparse (op), t, exprNode_unparse (e)),
4420 	     e->loc);
4421         }
4422       ret->typ = ctype_unknown;
4423     }
4424 
4425   /* if (ctype_isZero (t)) e->typ = ctype_int; */
4426 
4427   exprNode_checkModify (e, ret);
4428 
4429   /* added 7/11/2000 D.L */
4430 
4431   /* updateEnvironmentForPostOp (e); */
4432 
4433   /* start modifications */
4434   /* added by Seejo on 4/16/2000 */
4435 
4436   /* Arithmetic operations on pointers wil modify the size/len/null terminated
4437      status */
4438   if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4439 
4440     ret->sref = sRef_copy (e->sref);
4441 
4442     /* Operator : ++ */
4443     if (lltok_getTok (op) == INC_OP) {
4444       if (sRef_getSize(e->sref) > 0) {
4445 
4446 	sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4447 
4448 	if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4449 	  /* Assumption: there is only 1 \0 in the buffer */
4450 	  /* This will not be correct if there are 2 \0's in the buffer */
4451 	  sRef_setNotNullTerminatedState(ret->sref);
4452 	  sRef_resetLen(ret->sref);
4453 	} else {
4454 	  sRef_setNullTerminatedState(ret->sref);
4455 	  sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4456 	}
4457 	if (sRef_isNullTerminated (ret->sref))
4458 	  printf ("ret->sref is Null Terminated\n");
4459 	else if (sRef_isPossiblyNullTerminated (ret->sref))
4460 	  printf ("ret->sref is Possibly Null Terminated\n");
4461 	else if (sRef_isNotNullTerminated (ret->sref))
4462 	  printf ("ret->sref is Not Null Terminated\n");
4463 	else
4464 	  {}
4465       }
4466     }
4467 
4468     /* Operator : -- */
4469     if (lltok_getTok (op) == DEC_OP) {
4470       if (sRef_getSize(e->sref) >= 0) {
4471 	sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4472 	sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4473       }
4474     }
4475   }
4476   /* end modifications */
4477 
4478   return ret;
4479 }
4480 
4481 exprNode
exprNode_preOp(exprNode e,lltok op)4482 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4483 {
4484   bool checkMod = FALSE;
4485   ctype te, tr;
4486   int opid = lltok_getTok (op);
4487   exprNode ret = exprNode_createSemiCopy (e);
4488 
4489   exprNode_copySets (ret, e);
4490 
4491   multiVal_free (ret->val);
4492   ret->val = multiVal_undefined;
4493   ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4494   ret->kind = XPR_PREOP;
4495   ret->edata = exprData_makeUop (e, op);
4496 
4497   if (exprNode_isError (e))
4498     {
4499       return ret;
4500     }
4501 
4502   checkMacroParen (e);
4503 
4504   te = exprNode_getType (e);
4505   tr = ctype_realType (te);
4506 
4507   if (opid != TAMPERSAND)
4508     {
4509       exprNode_checkUse (ret, e->sref, e->loc);
4510 
4511       if (ctype_isRealAbstract (tr)
4512 	  && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4513 	{
4514 	  if (ctype_isRealNumAbstract (tr))
4515 	    {
4516 	      ; /* no warning for numabstract types */
4517 	    }
4518 	  else
4519 	    {
4520 	      if (optgenerror (FLG_ABSTRACT,
4521 			       message ("Operand of %s is abstract type (%t): %s",
4522 					lltok_unparse (op), tr,
4523 					exprNode_unparse (ret)),
4524 			       e->loc))
4525 		{
4526 		  tr = te = ctype_unknown;
4527 		  ret->typ = ctype_unknown;
4528 		  sRef_setNullError (e->sref);
4529 		}
4530 	    }
4531 	}
4532     }
4533 
4534   switch (opid)
4535     {
4536     case INC_OP:
4537     case DEC_OP:		/* should also check modification! */
4538       if (sRef_isMacroParamRef (e->sref))
4539 	{
4540 	  voptgenerror
4541 	    (FLG_MACROPARAMS,
4542 	     message ("Operand of %s is macro parameter (non-functional): %s",
4543 		      lltok_unparse (op), exprNode_unparse (ret)),
4544 	     e->loc);
4545 	}
4546       else
4547 	{
4548 	  exprNode_checkSet (ret, e->sref);
4549 	}
4550 
4551       if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4552 	{
4553 	}
4554       else
4555 	{
4556 	  if (context_msgStrictOps ())
4557 	    {
4558 	      voptgenerror
4559 		(FLG_STRICTOPS,
4560 		 message ("Operand of %s is non-numeric (%t): %s",
4561 			  lltok_unparse (op), te, exprNode_unparse (ret)),
4562 		 e->loc);
4563 	    }
4564 	  ret->typ = ctype_int;
4565 	}
4566 
4567   	/* start modifications */
4568 	/* added by Seejo on 4/16/2000 */
4569 
4570 	/* Arithmetic operations on pointers wil modify the size/len/null terminated
4571 		 status */
4572 	if ((sRef_isPossiblyNullTerminated (e->sref))
4573 	    || (sRef_isNullTerminated(e->sref))) {
4574 		ret->sref = sRef_copy (e->sref);
4575 
4576 		/* Operator : ++ */
4577 		if (lltok_getTok (op) == INC_OP) {
4578 			if (sRef_getSize(e->sref) > 0) {
4579 
4580 				sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4581 
4582 				if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4583 					/* Assumption: there is only 1 \0 in the buffer */
4584 					/* This will not be correct if there are 2 \0's in the buffer */
4585 					sRef_setNotNullTerminatedState(ret->sref);
4586 					sRef_resetLen (ret->sref);
4587 				} else {
4588 					sRef_setNullTerminatedState(ret->sref);
4589 					sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4590 				}
4591 			}
4592 		}
4593 
4594 		/* Operator : -- */
4595 		if (lltok_getTok (op) == DEC_OP) {
4596 			if (sRef_getSize(e->sref) >= 0) {
4597 				sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4598 				sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4599 			}
4600 		}
4601 	}
4602 
4603 	/* end modifications */
4604 
4605       checkMod = TRUE;
4606       break;
4607 
4608     case TMINUS:
4609     case TPLUS:
4610       if (ctype_isForceRealNumeric (&tr))
4611 	{
4612 	  if (opid == TMINUS)
4613 	    {
4614 	      ret->val = multiVal_invert (exprNode_getValue (e));
4615 	    }
4616 	  else
4617 	    {
4618 	      ret->val = multiVal_copy (exprNode_getValue (e));
4619 	    }
4620 	}
4621       else
4622 	{
4623 	  if (context_msgStrictOps ())
4624     	    {
4625 	      voptgenerror
4626 		(FLG_STRICTOPS,
4627 		 message ("Operand of %s is non-numeric (%t): %s",
4628 			  lltok_unparse (op), te, exprNode_unparse (ret)),
4629 		 e->loc);
4630 	    }
4631 
4632 	  ret->typ = ctype_int;
4633 	}
4634       break;
4635 
4636     case TEXCL:		/* maybe this should be restricted */
4637       guardSet_flip (ret->guards);
4638 
4639       if (ctype_isRealBool (te) || ctype_isUnknown (te))
4640 	{
4641 	 ;
4642 	}
4643       else
4644 	{
4645 	  if (ctype_isRealPointer (tr))
4646 	    {
4647 	      if (sRef_isKnown (e->sref))
4648 		{
4649 		  ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4650 		}
4651 
4652 	      voptgenerror2n
4653 		(FLG_BOOLOPS, FLG_PTRNEGATE,
4654 		 message ("Operand of %s is non-boolean (%t): %s",
4655 			  lltok_unparse (op), te, exprNode_unparse (ret)),
4656 		 e->loc);
4657 	    }
4658 	  else
4659 	    {
4660 	      voptgenerror
4661 		(FLG_BOOLOPS,
4662 		 message ("Operand of %s is non-boolean (%t): %s",
4663 			  lltok_unparse (op), te, exprNode_unparse (ret)),
4664 		 e->loc);
4665 	    }
4666 
4667 	  ret->typ = ctype_bool;
4668 	}
4669       break;
4670 
4671     case TTILDE:
4672       if (ctype_isForceRealInt (&tr))
4673 	{
4674 	}
4675       else
4676 	{
4677 	  if (context_msgStrictOps ())
4678 	    {
4679 	      voptgenerror
4680 		(FLG_STRICTOPS,
4681 		 message ("Operand of %s is non-integer (%t): %s",
4682 			  lltok_unparse (op), te, exprNode_unparse (ret)),
4683 		 e->loc);
4684 	    }
4685 
4686 	  if (ctype_isInt (e->typ))
4687 	    {
4688 	      ret->typ = e->typ;
4689 	    }
4690 	  else
4691 	    {
4692 	      ret->typ = ctype_int;
4693 	    }
4694 	}
4695       break;
4696 
4697     case TAMPERSAND:
4698       ret->typ = ctype_makePointer (e->typ);
4699 
4700       if (sRef_isKnown (e->sref))
4701 	{
4702 	  ret->sref = sRef_makeAddress (e->sref);
4703 	}
4704 
4705       break;
4706 
4707     case TMULT:
4708 
4709       if (ctype_isAP (tr))
4710 	{
4711 	  ret->typ = ctype_baseArrayPtr (e->typ);
4712 	}
4713       else
4714 	{
4715 	  if (ctype_isKnown (te))
4716 	    {
4717 	      if (ctype_isFunction (te))
4718 		{
4719 		  ret->typ = e->typ;
4720 
4721 		  voptgenerror
4722 		    (FLG_FCNDEREF,
4723 		     message ("Dereference of function type (%t): %s",
4724 			      te, exprNode_unparse (ret)),
4725 		     e->loc);
4726 		}
4727 	      else
4728 		{
4729 		  voptgenerror (FLG_TYPE,
4730 				message ("Dereference of non-pointer (%t): %s",
4731 					 te, exprNode_unparse (ret)),
4732 				e->loc);
4733 		  ret->typ = ctype_unknown;
4734 		}
4735 	    }
4736 	  else
4737 	    {
4738 	      ret->typ = ctype_unknown;
4739 	    }
4740 
4741 	}
4742 
4743       if (sRef_isKnown (e->sref))
4744 	{
4745 	  DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4746 
4747 	  if (sRef_possiblyNull (e->sref))
4748 	    {
4749 	      DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4750 	      if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4751 		{
4752 		  if (optgenerror
4753 		      (FLG_NULLDEREF,
4754 		       message ("Dereference of %s pointer %q: %s",
4755 				sRef_nullMessage (e->sref),
4756 				sRef_unparse (e->sref),
4757 				exprNode_unparse (ret)),
4758 		       e->loc))
4759 		    {
4760 		      sRef_showNullInfo (e->sref);
4761 		      sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4762 		    }
4763 		}
4764 	    }
4765 
4766 	  ret->sref = sRef_makePointer (e->sref);
4767 	}
4768       break;
4769 
4770     default:
4771       llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4772     }
4773 
4774   if (checkMod)
4775     {
4776       exprNode_checkModify (e, ret);
4777     }
4778 
4779   return ret;
4780 }
4781 
4782 /*
4783 ** any reason to disallow sizeof (abstract type) ?
4784 */
4785 
4786 /*
4787 ** used by both sizeof
4788 */
4789 
4790 static
sizeof_resultType(void)4791 ctype sizeof_resultType (void)
4792 {
4793   static ctype sizet = ctype_unknown;
4794 
4795   if (ctype_isUnknown (sizet))
4796     {
4797       if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4798 	{
4799 	  sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4800 	}
4801       else
4802 	{
4803 	  sizet = ctype_ulint;
4804 	}
4805     }
4806   return sizet;
4807 }
4808 
4809 exprNode
exprNode_sizeofType(qtype qt)4810 exprNode_sizeofType (/*@only@*/ qtype qt)
4811 {
4812   exprNode ret = exprNode_create (sizeof_resultType ());
4813   ctype ct = qtype_getType (qt);
4814 
4815   ret->kind = XPR_SIZEOFT;
4816   ret->edata = exprData_makeSizeofType (qt);
4817 
4818   voptgenerror (FLG_SIZEOFTYPE,
4819 		message ("Parameter to sizeof is type %s: %s",
4820 			 ctype_unparse (ct),
4821 			 exprNode_unparse (ret)),
4822 		ret->loc);
4823 
4824   return (ret);
4825 }
4826 
4827 exprNode
exprNode_alignofType(qtype qt)4828 exprNode_alignofType (/*@only@*/ qtype qt)
4829 {
4830   exprNode ret = exprNode_create (sizeof_resultType ());
4831   ctype ct = qtype_getType (qt);
4832 
4833   ret->kind = XPR_ALIGNOFT;
4834   ret->edata = exprData_makeSizeofType (qt);
4835 
4836   voptgenerror (FLG_SIZEOFTYPE,
4837 		message ("Parameter to alignof is type %s: %s",
4838 			 ctype_unparse (ct),
4839 			 exprNode_unparse (ret)),
4840 		ret->loc);
4841 
4842   return (ret);
4843 }
4844 
exprNode_offsetof(qtype qt,cstringList s)4845 exprNode exprNode_offsetof (qtype qt, cstringList s)
4846 {
4847   exprNode ret = exprNode_create (sizeof_resultType ());
4848   ctype ct = qtype_getType (qt);
4849 
4850   ret->kind = XPR_OFFSETOF;
4851   ret->edata = exprData_makeOffsetof (qt, s);
4852 
4853   if (!ctype_isRealSU (ct))
4854     {
4855       voptgenerror (FLG_TYPE,
4856 		    message ("First parameter to offsetof is not a "
4857 			     "struct or union type (type %s): %s",
4858 			     ctype_unparse (ct),
4859 			     exprNode_unparse (ret)),
4860 		    ret->loc);
4861     }
4862   else
4863     {
4864       ctype lt = ct;
4865 
4866       cstringList_elements (s, el) {
4867 	uentryList fields;
4868 	uentry fld;
4869 
4870 	if (ctype_isUndefined (lt))
4871 	  {
4872 	    break;
4873 	  }
4874 	else if (!ctype_isRealSU (lt))
4875 	  {
4876 	    voptgenerror (FLG_TYPE,
4877 			  message ("Inner offsetof type is not a "
4878 				   "struct or union type (type %s before field %s): %s",
4879 				   ctype_unparse (lt), el,
4880 				   exprNode_unparse (ret)),
4881 			  ret->loc);
4882 	    break;
4883 	  }
4884 	else
4885 	  {
4886 	    fields = ctype_getFields (ctype_realType (lt));
4887 	    fld = uentryList_lookupField (fields, el);
4888 	    DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4889 
4890 	    if (uentry_isUndefined (fld))
4891 	      {
4892 		if (ctype_equal (lt, ct)) {
4893 		  voptgenerror (FLG_TYPE,
4894 				message ("Field %s in offsetof is not the "
4895 					 "name of a field of %s: %s",
4896 					 el,
4897 					 ctype_unparse (ct),
4898 					 exprNode_unparse (ret)),
4899 				ret->loc);
4900 		} else {
4901 		  voptgenerror (FLG_TYPE,
4902 				message ("Deep field %s in offsetof is not the "
4903 					 "name of a field of %s: %s",
4904 					 el,
4905 					 ctype_unparse (lt),
4906 					 exprNode_unparse (ret)),
4907 				ret->loc);
4908 		}
4909 	      }
4910 	    else
4911 	      {
4912 		lt = uentry_getType (fld);
4913 	      }
4914 	  }
4915       } end_cstringList_elements;
4916 
4917       /* Should report error if its a bit field - behavior is undefined! */
4918     }
4919 
4920   return (ret);
4921 }
4922 
4923 /*@only@*/ exprNode
exprNode_sizeofExpr(exprNode e)4924 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4925 {
4926   exprNode ret;
4927 
4928   if (exprNode_isUndefined (e))
4929     {
4930       ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4931       ret->edata = exprData_makeSingle (e);
4932       ret->typ = sizeof_resultType ();
4933       ret->kind = XPR_SIZEOF;
4934     }
4935   else
4936     {
4937       uentry u = exprNode_getUentry (e);
4938 
4939       ret = exprNode_createPartialCopy (e);
4940       ret->edata = exprData_makeSingle (e);
4941 
4942       ret->typ = sizeof_resultType ();
4943       ret->kind = XPR_SIZEOF;
4944 
4945       if (uentry_isValid (u)
4946 	  && uentry_isRefParam (u)
4947 	  && ctype_isRealArray (uentry_getType (u)))
4948 	{
4949 	  voptgenerror
4950 	    (FLG_SIZEOFFORMALARRAY,
4951 	     message ("Parameter to sizeof is an array-type function parameter: %s",
4952 		      exprNode_unparse (ret)),
4953 	     ret->loc);
4954 	}
4955     }
4956 
4957   /*
4958   ** sizeof (x) doesn't "really" use x
4959   */
4960 
4961   return (ret);
4962 }
4963 
4964 /*@only@*/ exprNode
exprNode_alignofExpr(exprNode e)4965 exprNode_alignofExpr (/*@only@*/ exprNode e)
4966 {
4967   exprNode ret;
4968 
4969   if (exprNode_isUndefined (e))
4970     {
4971       ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4972     }
4973   else
4974     {
4975       ret = exprNode_createPartialCopy (e);
4976     }
4977 
4978   ret->edata = exprData_makeSingle (e);
4979   ret->typ = sizeof_resultType ();
4980   ret->kind = XPR_ALIGNOF;
4981 
4982   /*
4983   ** sizeof (x) doesn't "really" use x
4984   */
4985 
4986   return (ret);
4987 }
4988 
4989 /*@only@*/ exprNode
exprNode_cast(lltok tok,exprNode e,qtype q)4990 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4991 {
4992   ctype c;
4993   ctype t;
4994   exprNode ret;
4995 
4996   if (exprNode_isError (e))
4997     {
4998       qtype_free (q);
4999       lltok_free (tok);
5000       return exprNode_undefined;
5001     }
5002 
5003   checkMacroParen (e);
5004 
5005   c = qtype_getType (q);
5006   t = exprNode_getType (e);
5007 
5008   ret = exprNode_createPartialCopy (e);
5009 
5010   ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
5011   ret->typ = c;
5012   ret->kind = XPR_CAST;
5013   ret->edata = exprData_makeCast (tok, e, q);
5014 
5015   ret->sref = sRef_copy (e->sref);
5016 
5017   DPRINTF (("Cast: -> %s", sRef_unparseFull (ret->sref)));
5018 
5019   if (!sRef_isConst (e->sref))
5020     {
5021       usymtab_addForceMustAlias (ret->sref, e->sref);
5022     }
5023 
5024   DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5025   sRef_setTypeFull (ret->sref, c);
5026   DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5027 
5028   /*
5029   ** we allow
5030   **       abstract  -> void
5031   **              0 <-> abstract *
5032   **         void * <-> abstract *  (if FLG_ABSTVOIDP)
5033   **     abstract * <-> void *      (if FLG_ABSTVOIDP)
5034   */
5035 
5036   if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
5037     {
5038       /* evans 2002-07-19: added this warning */
5039       DPRINTF (("Checking: %s / %s", exprNode_unparse (ret), sRef_unparseFull (ret->sref)));
5040       if (sRef_isFresh (ret->sref))
5041 	{
5042 	  voptgenerror
5043 	    (FLG_MUSTFREEFRESH,
5044 	     message ("New fresh storage %q(type %s) cast to void (not released): %s",
5045 		      sRef_unparseOpt (ret->sref),
5046 		      ctype_unparse (exprNode_getType (ret)),
5047 		      exprNode_unparse (ret)),
5048 	     exprNode_loc (ret));
5049 	}
5050     }
5051   else if (ctype_isRealAP (c)) /* casting to array or pointer */
5052     {
5053       ctype bc = ctype_getBaseType (c);
5054       ctype bt = ctype_getBaseType (t);
5055       ctype rt = ctype_realType (t);
5056 
5057       if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
5058 	  && (ctype_isArrayPtr (rt)
5059 	      && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5060 	{
5061 	  voptgenerror
5062 	    (FLG_CASTFCNPTR,
5063 	     message ("Cast from function pointer type (%t) to "
5064 		      "non-function pointer (%t): %s",
5065 		      c, t, exprNode_unparse (ret)),
5066 	     e->loc);
5067 	}
5068 
5069       if (!ctype_isFunction (ctype_baseArrayPtr (c))
5070 	  && (ctype_isArrayPtr (rt)
5071 	      && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5072 	{
5073 	  voptgenerror
5074 	    (FLG_CASTFCNPTR,
5075 	     message ("Cast from non-function pointer type (%t) to "
5076 		      "function pointer (%t): %s",
5077 		      c, t, exprNode_unparse (ret)),
5078 	     e->loc);
5079 	}
5080 
5081       if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5082 	  !(ctype_isRealAbstract (bc)
5083 	    && context_hasAccess (ctype_typeId (bc))))
5084 	{
5085 	 ; /* okay to cast zero */
5086 	}
5087       else
5088 	{
5089 	  if (ctype_isRealAbstract (bc)
5090 	      && !context_hasAccess (ctype_typeId (bc)))
5091 	    {
5092 	      if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5093 		{
5094 		  vnoptgenerror
5095 		    (FLG_ABSTVOIDP,
5096 		     message ("Cast to underlying abstract type %t: %s",
5097 			      c, exprNode_unparse (ret)),
5098 		     e->loc);
5099 		}
5100 	      else
5101 		{
5102 		  voptgenerror
5103 		    (FLG_ABSTRACT,
5104 		     message ("Cast to underlying abstract type %t: %s",
5105 			      c, exprNode_unparse (ret)),
5106 		     e->loc);
5107 		}
5108 	    }
5109 
5110 	  if (ctype_isRealAbstract (bt)
5111 	      && !context_hasAccess (ctype_typeId (bt)))
5112 	    {
5113 	      if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5114 		{
5115 		  vnoptgenerror
5116 		    (FLG_ABSTVOIDP,
5117 		     message ("Cast from underlying abstract type %t: %s",
5118 			      t, exprNode_unparse (ret)),
5119 		     e->loc);
5120 		}
5121 	      else
5122 		{
5123 		  voptgenerror
5124 		    (FLG_ABSTRACT,
5125 		     message ("Cast from underlying abstract type %t: %s",
5126 			      t, exprNode_unparse (ret)),
5127 		     e->loc);
5128 		}
5129 	    }
5130 	}
5131     }
5132   else
5133     {
5134       ctype bt = ctype_realType (ctype_getBaseType (t));
5135       ctype bc = ctype_realType (ctype_getBaseType (c));
5136 
5137       if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5138 	{
5139 	  if (ctype_match (c, t))
5140 	    {
5141 	      if (ctype_equal (c, t))
5142 		{
5143 		  voptgenerror
5144 		    (FLG_TYPE,
5145 		     message ("Redundant cast involving abstract type %t: %s",
5146 			      bt, exprNode_unparse (ret)),
5147 		     e->loc);
5148 		}
5149 	    }
5150 	  else
5151 	    {
5152 	      voptgenerror
5153 		(FLG_ABSTRACT,
5154 		 message ("Cast from abstract type %t: %s",
5155 			  bt, exprNode_unparse (ret)),
5156 		 e->loc);
5157 	    }
5158 	}
5159 
5160       if (ctype_isAbstract (bc)
5161 	  && !context_hasAccess (ctype_typeId (bc)))
5162 	{
5163 	  if (ctype_match (c, t))
5164 	    {
5165 	     ;
5166 	    }
5167 	  else
5168 	    {
5169 	      if (ctype_isNumAbstract (bc))
5170 		{
5171 		  if (exprNode_isNumLiteral (e))
5172 		    {
5173 		      voptgenerror
5174 			(FLG_NUMABSTRACTCAST,
5175 			 message ("Cast from literal to numabstract type %t: %s", bc,
5176 				  exprNode_unparse (ret)),
5177 			 e->loc);
5178 		    }
5179 		  else
5180 		    {
5181 		      voptgenerror
5182 			(FLG_NUMABSTRACT,
5183 			 message ("Cast to numabstract type %t: %s", bc,
5184 				  exprNode_unparse (ret)),
5185 			 e->loc);
5186 		    }
5187 		}
5188 	      else
5189 		{
5190 		  DPRINTF (("No access to: %s / %d",
5191 			    ctype_unparse (bc), ctype_typeId (bc)));
5192 		  DPRINTF (("Context %s %s",
5193 			    bool_unparse (context_inFunctionLike ()),
5194 			    context_unparse ()));
5195 		  voptgenerror
5196 		    (FLG_ABSTRACT,
5197 		     message ("Cast to abstract type %t: %s", bc,
5198 			      exprNode_unparse (ret)),
5199 		     e->loc);
5200 		}
5201 	    }
5202 	}
5203     }
5204 
5205   if (ctype_isAbstract (c))
5206     {
5207       if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5208 	{
5209 	  /* okay, cast exposed to abstract */
5210 	  sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5211 	}
5212       else
5213 	{
5214 	  if (ctype_isVisiblySharable (t)
5215 	      && sRef_isExternallyVisible (e->sref)
5216 	      && !(ctype_isAbstract (t)
5217 		   && context_hasAccess (ctype_typeId (t))))
5218 	    {
5219 	      voptgenerror
5220 		(FLG_CASTEXPOSE,
5221 		 message ("Cast to abstract type from externally visible "
5222 			  "mutable storage exposes rep of %s: %s",
5223 			  ctype_unparse (c),
5224 			  exprNode_unparse (e)),
5225 		 e->loc);
5226 	    }
5227 	}
5228     }
5229 
5230   return (ret);
5231 }
5232 
5233 static bool
evaluationOrderUndefined(lltok op)5234 evaluationOrderUndefined (lltok op)
5235 {
5236   int opid = lltok_getTok (op);
5237 
5238   return (opid != AND_OP && opid != OR_OP);
5239 }
5240 
checkIntegral(exprNode e1,exprNode e2,exprNode ret,lltok op)5241 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5242 			   /*@notnull@*/ exprNode e2,
5243 			   /*@notnull@*/ exprNode ret,
5244 			   lltok op)
5245 {
5246   bool error = FALSE;
5247 
5248   ctype te1 = exprNode_getType (e1);
5249   ctype te2 = exprNode_getType (e2);
5250 
5251   ctype tr1 = ctype_realishType (te1);
5252   ctype tr2 = ctype_realishType (te2);
5253 
5254   if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5255     {
5256       ;
5257     }
5258   else
5259     {
5260       if (context_msgStrictOps ())
5261 	{
5262 	  if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5263 	    {
5264 	      if (ctype_sameName (te1, te2))
5265 		{
5266 		  error = optgenerror
5267 		    (FLG_STRICTOPS,
5268 		     message ("Operands of %s are non-integer (%t): %s",
5269 			      lltok_unparse (op), te1,
5270 			      exprNode_unparse (ret)),
5271 		     e1->loc);
5272 		}
5273 	      else
5274 		{
5275 		  error = optgenerror
5276 		    (FLG_STRICTOPS,
5277 		     message ("Operands of %s are non-integers (%t, %t): %s",
5278 			      lltok_unparse (op), te1, te2,
5279 			      exprNode_unparse (ret)),
5280 		     e1->loc);
5281 		}
5282 	    }
5283 	  else if (!ctype_isInt (tr1))
5284 	    {
5285 	      error = optgenerror
5286 		(FLG_STRICTOPS,
5287 		 message ("Left operand of %s is non-integer (%t): %s",
5288 			  lltok_unparse (op), te1, exprNode_unparse (ret)),
5289 		 e1->loc);
5290 	    }
5291 	  else
5292 	    /* !ctype_isInt (te2) */
5293 	    {
5294 	      error = optgenerror
5295 		(FLG_STRICTOPS,
5296 		 message ("Right operand of %s is non-integer (%t): %s",
5297 			  lltok_unparse (op), te2, exprNode_unparse (ret)),
5298 		 e2->loc);
5299 	    }
5300 	}
5301     }
5302 
5303   return !error;
5304 }
5305 
5306 /*
5307 ** returns exprNode representing e1 op e2
5308 **
5309 ** uses msg if there are errors
5310 ** can be used for both assignment ops and regular ops
5311 **
5312 ** modifies e1
5313 */
5314 
5315 static /*@only@*/ /*@notnull@*/ exprNode
exprNode_makeOp(exprNode e1,exprNode e2,lltok op)5316 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5317 		 /*@keep@*/ lltok op)
5318 {
5319   ctype te1, te2, tr1, tr2, tret;
5320   int opid = lltok_getTok (op);
5321   bool hasError = FALSE;
5322   exprNode ret;
5323 
5324   if (exprNode_isError (e1))
5325     {
5326       ret = exprNode_createPartialNVCopy (e2);
5327     }
5328   else
5329     {
5330       ret = exprNode_createPartialNVCopy (e1);
5331     }
5332 
5333   ret->val = multiVal_undefined;
5334 
5335   ret->kind = XPR_OP;
5336   ret->edata = exprData_makeOp (e1, e2, op);
5337 
5338   if (exprNode_isError (e1) || exprNode_isError (e2))
5339     {
5340       if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5341 	  || opid == EQ_OP || opid == NE_OP
5342 	  || opid == AND_OP || opid == OR_OP)
5343 	{
5344 	  ret->typ = ctype_bool;
5345 	}
5346 
5347       if (exprNode_isDefined (e1))
5348 	{
5349 	  exprNode_checkUse (ret, e1->sref, e1->loc);
5350 	}
5351 
5352       if (exprNode_isDefined (e2))
5353 	{
5354 	  exprNode_mergeUSs (ret, e2);
5355 	  exprNode_checkUse (ret, e2->sref, e2->loc);
5356 	}
5357 
5358       return ret;
5359     }
5360 
5361   tret = ctype_unknown;
5362   te1 = exprNode_getType (e1);
5363 
5364   DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5365 
5366   te2 = exprNode_getType (e2);
5367 
5368   tr1 = ctype_realishType (te1);
5369   tr2 = ctype_realishType (te2);
5370 
5371   if (opid == OR_OP)
5372     {
5373       exprNode_produceGuards (e2);
5374       ret->guards = guardSet_or (ret->guards, e2->guards);
5375     }
5376   else if (opid == AND_OP)
5377     {
5378       exprNode_produceGuards (e2); /* evans 2003-08-13: need to produce guards for expression */
5379       /* Shouldn't this have already happened? */
5380       DPRINTF (("Anding guards: %s / %s", guardSet_unparse (ret->guards), guardSet_unparse (e2->guards)));
5381       ret->guards = guardSet_and (ret->guards, e2->guards);
5382     }
5383   else
5384     {
5385       /* no guards */
5386     }
5387 
5388   if (opid == EQ_OP || opid == NE_OP)
5389     {
5390       exprNode temp1 = e1, temp2 = e2;
5391 
5392       /* could do NULL == x */
5393 
5394       if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5395 	{
5396 	  temp1 = e2; temp2 = e1;
5397 	}
5398 
5399       if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5400 	{
5401 	  reflectNullTest (temp1, (opid == NE_OP));
5402 	  guardSet_free (ret->guards);
5403 	  ret->guards = guardSet_copy (temp1->guards);
5404 	}
5405     }
5406 
5407   if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5408       || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5409     {
5410       tret = ctype_bool;
5411     }
5412 
5413   if (anyAbstract (tr1, tr2) &&
5414       (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5415 	 (opid == AND_OP || opid == OR_OP
5416 	  || opid == EQ_OP || opid == NE_OP))))
5417     {
5418       if (abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc))
5419 	{
5420 	  tret = ctype_unknown;
5421 	  goto skiprest;
5422 	}
5423     }
5424 
5425   if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5426     {
5427       /* unknown types, no comparisons possible */
5428       goto skiprest;
5429     }
5430 
5431   switch (opid)
5432     {
5433     case TMULT:		/* multiplication and division:           */
5434     case TDIV:		/*                                        */
5435     case MUL_ASSIGN:	/*    numeric, numeric -> numeric         */
5436     case DIV_ASSIGN:	/*                                        */
5437       if (opid == TMULT || opid == MUL_ASSIGN)
5438 	{
5439 	  ret->val = multiVal_multiply (exprNode_getValue (e1),
5440 					exprNode_getValue (e2));
5441 	}
5442       else
5443 	{
5444 	  ret->val = multiVal_divide (exprNode_getValue (e1),
5445 				      exprNode_getValue (e2));
5446 	}
5447 
5448       tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5449       break;
5450 
5451     case TPLUS:		/* addition and subtraction:               */
5452     case TMINUS:	/*    pointer, int     -> pointer          */
5453     case SUB_ASSIGN:	/*    int, pointer     -> pointer          */
5454     case ADD_ASSIGN:	/*    numeric, numeric -> numeric          */
5455       if (opid == TPLUS || opid == ADD_ASSIGN)
5456 	{
5457 	  ret->val = multiVal_add (exprNode_getValue (e1),
5458 				   exprNode_getValue (e2));
5459 	}
5460       else
5461 	{
5462 	  ret->val = multiVal_subtract (exprNode_getValue (e1),
5463 					exprNode_getValue (e2));
5464 	}
5465 
5466       tr1 = ctype_fixArrayPtr (tr1);
5467 
5468       if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5469 	  && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5470 	{
5471 	  /* pointer + int */
5472 
5473 	  if (context_msgPointerArith ())
5474 	    {
5475 	      voptgenerror
5476 		(FLG_POINTERARITH,
5477 		 message ("Pointer arithmetic (%t, %t): %s",
5478 			  te1, te2, exprNode_unparse (ret)),
5479 		 e1->loc);
5480 	    }
5481 
5482 	  /*
5483 	  ** Swap terms so e1 is always the pointer
5484 	  */
5485 
5486 	  if (ctype_isRealPointer (tr1))
5487 	    {
5488 	      ;
5489 	    }
5490 	  else
5491 	    {
5492 	      exprNode_swap (e1, e2);
5493 	    }
5494 
5495 	  if (sRef_possiblyNull (e1->sref)
5496 	      && !usymtab_isGuarded (e1->sref))
5497 	    {
5498 	      voptgenerror
5499 		(FLG_NULLPOINTERARITH,
5500 		 message ("Pointer arithmetic involving possibly "
5501 			  "null pointer %s: %s",
5502 			  exprNode_unparse (e1),
5503 			  exprNode_unparse (ret)),
5504 		 e1->loc);
5505 	    }
5506 
5507 	  ret->sref = sRef_copy (e1->sref);
5508 
5509 	  /* start modifications */
5510 	  /* added by Seejo on 4/16/2000 */
5511 
5512 	  /* Arithmetic operations on pointers wil modify the size/len/null terminated
5513 	     status */
5514 	  if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5515 	    int val;
5516 	    /*drl 1-4-2002
5517 	      added ugly fixed to stop
5518 	      program from crashing on point + int +int
5519 	      one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5520 
5521 	    if (!multiVal_isInt (e2->val) )
5522 	      break;
5523 	    /*end drl*/
5524 
5525 	    val = (int) multiVal_forceInt (e2->val);
5526 
5527 	    /* Operator : + or += */
5528 	    if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5529 	      if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5530 						     val should not result in a
5531 						     size < 0 (size = 0 is ok !) */
5532 
5533 		sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5534 
5535 		if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5536 		  sRef_setNotNullTerminatedState(ret->sref);
5537 		  sRef_resetLen (ret->sref);
5538 		} else {
5539 		  sRef_setNullTerminatedState(ret->sref);
5540 		  sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5541 		}
5542 	      }
5543 	    }
5544 
5545 	    /* Operator : - or -= */
5546 	    if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5547 	      if (sRef_getSize(e1->sref) >= 0) {
5548 		sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5549 		sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5550 	      }
5551 	    }
5552 	  }
5553 
5554 	  /* end modifications */
5555 
5556 	  sRef_setNullError (ret->sref);
5557 
5558 	  /*
5559 	  ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5560 	  ** since is points to storage that should not be deallocated
5561 	  ** through this pointer.
5562 	  */
5563 
5564 	  if (sRef_isOnly (ret->sref)
5565 	      || sRef_isFresh (ret->sref))
5566 	    {
5567 	      sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5568 	    }
5569 
5570 	  tret = e1->typ;
5571 	}
5572       else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5573 	       && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5574 	{
5575 	  if (context_msgPointerArith ())
5576 	    {
5577 	      voptgenerror
5578 		(FLG_POINTERARITH,
5579 		 message ("Pointer arithmetic (%t, %t): %s",
5580 			  te1, te2, exprNode_unparse (ret)),
5581 		 e1->loc);
5582 	    }
5583 
5584 	  if (sRef_possiblyNull (e1->sref)
5585 	      && !usymtab_isGuarded (e1->sref))
5586 	    {
5587 	      voptgenerror
5588 		(FLG_NULLPOINTERARITH,
5589 		 message ("Pointer arithmetic involving possibly "
5590 			  "null pointer %s: %s",
5591 			  exprNode_unparse (e2),
5592 			  exprNode_unparse (ret)),
5593 		 e2->loc);
5594 	    }
5595 
5596 	  ret->sref = sRef_copy (e2->sref);
5597 
5598 	  /* start modifications */
5599 	  /* added by Seejo on 4/16/2000 */
5600 
5601 	  /* Arithmetic operations on pointers wil modify the size/len/null terminated
5602 	     status */
5603 
5604 	  if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5605 	    if (multiVal_isDefined (e1->val))
5606 	      {
5607 		int val = (int) multiVal_forceInt (e1->val);
5608 
5609 		/* Operator : + or += */
5610 		if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5611 		  if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5612 							 val should not result in a
5613 							 size < 0 (size = 0 is ok !) */
5614 
5615 		    sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5616 
5617 		    if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5618 		      sRef_setNotNullTerminatedState(ret->sref);
5619 		      sRef_resetLen (ret->sref);
5620 		    } else {
5621 		      sRef_setNullTerminatedState(ret->sref);
5622 		      sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5623 		    }
5624 		  }
5625 		}
5626 
5627 		/* Operator : - or -= */
5628 		if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5629 		  if (sRef_getSize(e2->sref) >= 0) {
5630 		    sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5631 		    sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5632 		  }
5633 		}
5634 	      }
5635 	  }
5636 
5637 	  /* end modifications */
5638 
5639 	  sRef_setNullError (ret->sref);
5640 
5641 	  /*
5642 	  ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5643 	  ** since is points to storage that should not be deallocated
5644 	  ** through this pointer.
5645 	  */
5646 
5647 	  if (sRef_isOnly (ret->sref)
5648 	      || sRef_isFresh (ret->sref)) {
5649 	    sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5650 	  }
5651 
5652 	  tret = e2->typ;
5653 	  ret->sref = e2->sref;
5654 	}
5655       else
5656 	{
5657 	  tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5658 	}
5659 
5660       break;
5661 
5662     case LEFT_ASSIGN:
5663     case RIGHT_ASSIGN:
5664     case LEFT_OP:
5665     case RIGHT_OP:
5666     case TAMPERSAND:    /* bitwise & */
5667     case AND_ASSIGN:
5668     case TCIRC:         /* ^ (XOR) */
5669     case TBAR:
5670     case XOR_ASSIGN:
5671     case OR_ASSIGN:
5672       {
5673 	bool reported = FALSE;
5674 
5675 	/*
5676 	** Shift Operator
5677 	*/
5678 
5679 	if (opid == LEFT_OP || opid == LEFT_ASSIGN
5680 	    || opid == RIGHT_OP || opid == RIGHT_ASSIGN)
5681 	  {
5682 	    /*
5683 	    ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5684 	    */
5685 
5686 	    if (!ctype_isUnsigned (tr2)
5687 		&& !exprNode_isNonNegative (e2))
5688 	      {
5689 		reported = optgenerror
5690 		  (FLG_SHIFTNEGATIVE,
5691 		   message ("Right operand of %s may be negative (%t): %s",
5692 			    lltok_unparse (op), te2,
5693 			    exprNode_unparse (ret)),
5694 		   e2->loc);
5695 	      }
5696 
5697 	    if (!ctype_isUnsigned (tr1)
5698 		&& !exprNode_isNonNegative (e1))
5699 	      {
5700 		reported = optgenerror
5701 		  (FLG_SHIFTIMPLEMENTATION,
5702 		   message ("Left operand of %s may be negative (%t): %s",
5703 			    lltok_unparse (op), te1,
5704 			    exprNode_unparse (ret)),
5705 		   e1->loc);
5706 	      }
5707 
5708 	    /*
5709 	    ** Should check size of right operand also...
5710 	    */
5711 
5712 	  }
5713 	else
5714 	  {
5715 	    if (!ctype_isUnsigned (tr1))
5716 	      {
5717 		if (exprNode_isNonNegative (e1)) {
5718 		  ;
5719 		} else {
5720 		  reported = optgenerror
5721 		    (FLG_BITWISEOPS,
5722 		     message ("Left operand of %s is not unsigned value (%t): %s",
5723 			      lltok_unparse (op), te1,
5724 			      exprNode_unparse (ret)),
5725 		     e1->loc);
5726 
5727 		  if (reported) {
5728 		    te1 = ctype_uint;
5729 		  }
5730 		}
5731 	      }
5732 	    else
5733 	      {
5734 		if (!ctype_isUnsigned (tr2))
5735 		  {
5736 		    if (!exprNode_isNonNegative (e2)) {
5737 		      reported = optgenerror
5738 			(FLG_BITWISEOPS,
5739 			 message ("Right operand of %s is not unsigned value (%t): %s",
5740 				  lltok_unparse (op), te2,
5741 				  exprNode_unparse (ret)),
5742 			 e2->loc);
5743 		    }
5744 		  }
5745 	      }
5746 	  }
5747 
5748 	if (!reported)
5749 	  {
5750 	    if (!checkIntegral (e1, e2, ret, op)) {
5751 	      te1 = ctype_unknown;
5752 	    }
5753 	  }
5754 
5755 	DPRINTF (("Set: %s", ctype_unparse (te1)));
5756 
5757 	/*
5758 	** tret is the widest type of te1 and te2
5759 	*/
5760 
5761 	tret = ctype_widest (te1, te2);
5762 	break;
5763       }
5764     case MOD_ASSIGN:
5765     case TPERCENT:
5766       if (checkIntegral (e1, e2, ret, op)) {
5767 	tret = te1;
5768       } else {
5769 	tret = ctype_unknown;
5770       }
5771       break;
5772     case EQ_OP:
5773     case NE_OP:
5774     case TLT:		/* comparisons                           */
5775     case TGT:		/*    numeric, numeric -> bool           */
5776 
5777       DPRINTF (("Here we go: %s / %s",
5778 		ctype_unparse (tr1), ctype_unparse (tr2)));
5779 
5780       if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5781 	  || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5782 	{
5783 	  ctype rtype = tr1;
5784 	  bool fepsilon = FALSE;
5785 
5786 	  if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5787 	    {
5788 	      rtype = tr2;
5789 	    }
5790 
5791 	  if (opid == TLT || opid == TGT)
5792 	    {
5793 	      uentry ue1 = exprNode_getUentry (e1);
5794 	      uentry ue2 = exprNode_getUentry (e2);
5795 
5796 	      /*
5797 	      ** FLT_EPSILON, etc. really is a variable, not
5798 	      ** a constant.
5799 	      */
5800 
5801 	      if (uentry_isVariable (ue1))
5802 		{
5803 		  cstring uname = uentry_rawName (ue1);
5804 
5805 		  if (cstring_equalLit (uname, "FLT_EPSILON")
5806 		      || cstring_equalLit (uname, "DBL_EPSILON")
5807 		      || cstring_equalLit (uname, "LDBL_EPSILON"))
5808 		    {
5809 		      fepsilon = TRUE;
5810 		    }
5811 		}
5812 
5813 	      if (uentry_isVariable (ue2))
5814 		{
5815 		  cstring uname = uentry_rawName (ue2);
5816 
5817 		  if (cstring_equalLit (uname, "FLT_EPSILON")
5818 		      || cstring_equalLit (uname, "DBL_EPSILON")
5819 		      || cstring_equalLit (uname, "LDBL_EPSILON"))
5820 		    {
5821 		      fepsilon = TRUE;
5822 		    }
5823 		}
5824 	    }
5825 
5826 	  if (fepsilon)
5827 	    {
5828 	      ; /* Don't complain. */
5829 	    }
5830 	  else
5831 	    {
5832 	      if (opid == EQ_OP || opid == NE_OP)
5833 		{
5834 		  voptgenerror
5835 		    (FLG_REALCOMPARE,
5836 		     message ("Dangerous equality comparison involving %s types: %s",
5837 			      ctype_unparse (rtype),
5838 			      exprNode_unparse (ret)),
5839 		     ret->loc);
5840 		}
5841 	      else
5842 		{
5843 		  voptgenerror
5844 		    (FLG_REALRELATECOMPARE,
5845 		     message ("Possibly dangerous relational comparison involving %s types: %s",
5846 			      ctype_unparse (rtype),
5847 			      exprNode_unparse (ret)),
5848 		     ret->loc);
5849 		}
5850 	    }
5851 	}
5852       /*@fallthrough@*/
5853     case LE_OP:
5854     case GE_OP:
5855 
5856       /*
5857       ** Types should match.
5858       */
5859 
5860       DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5861 		exprNode_unparse (e2)));
5862 
5863       if (!exprNode_matchTypes (e1, e2))
5864 	{
5865 	  hasError = gentypeerror
5866 	    (te1, e1, te2, e2,
5867 	     message ("Operands of %s have incompatible types (%t, %t): %s",
5868 		      lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5869 	     e1->loc);
5870 
5871 	}
5872 
5873       if (hasError
5874 	  || (ctype_isForceRealNumeric (&tr1)
5875 	      && ctype_isForceRealNumeric (&tr2)) ||
5876 	  (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5877 	{
5878 	  ; /* okay */
5879 	}
5880       else
5881 	{
5882 	  if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5883 	      (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5884 	    {
5885 	      voptgenerror
5886 		(FLG_PTRNUMCOMPARE,
5887 		 message ("Comparison of pointer and numeric (%t, %t): %s",
5888 			  te1, te2, exprNode_unparse (ret)),
5889 		 e1->loc);
5890 	    }
5891 	  else
5892 	    {
5893 	      (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5894 	    }
5895 	  tret = ctype_bool;
5896 	}
5897 
5898       /* certain comparisons on unsigned's and zero look suspicious */
5899 
5900       if (opid == TLT || opid == LE_OP || opid == GE_OP)
5901 	{
5902 	  if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5903 	      || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5904 	    {
5905 	      voptgenerror
5906 		(FLG_UNSIGNEDCOMPARE,
5907 		 message ("Comparison of unsigned value involving zero: %s",
5908 			  exprNode_unparse (ret)),
5909 		 e1->loc);
5910 	    }
5911 	}
5912 
5913       /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5914 
5915       if ((opid == EQ_OP || opid == NE_OP) &&
5916 	  ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5917 	{
5918 	  /*
5919 	  ** is one a variable?
5920 	  */
5921 
5922 	  if (uentry_isVariable (exprNode_getUentry (e1))
5923 	      || uentry_isVariable (exprNode_getUentry (e2)))
5924 	    {
5925 	      /*
5926 	      ** comparisons with FALSE are okay
5927 	      */
5928 
5929 	      if (exprNode_isFalseConstant (e1)
5930 		  || exprNode_isFalseConstant (e2))
5931 		{
5932 		  ;
5933 		}
5934 	      else
5935 		{
5936 		  voptgenerror
5937 		    (FLG_BOOLCOMPARE,
5938 		     message
5939 		     ("Use of %q with %s variables (risks inconsistency because "
5940 		      "of multiple true values): %s",
5941 		      cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5942 		      context_printBoolName (), exprNode_unparse (ret)),
5943 		     e1->loc);
5944 		}
5945 	    }
5946 	}
5947       break;
5948 
5949     case AND_OP:		/* bool, bool -> bool */
5950     case OR_OP:
5951       if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5952 	{
5953 	  ;
5954 	}
5955       else
5956 	{
5957 	  if (context_maybeSet (FLG_BOOLOPS))
5958 	    {
5959 	      if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5960 		{
5961 		  if (ctype_sameName (te1, te2))
5962 		    {
5963 		      voptgenerror
5964 			(FLG_BOOLOPS,
5965 			 message ("Operands of %s are non-boolean (%t): %s",
5966 				  lltok_unparse (op), te1,
5967 				  exprNode_unparse (ret)),
5968 			 e1->loc);
5969 		    }
5970 		  else
5971 		    {
5972 		      voptgenerror
5973 			(FLG_BOOLOPS,
5974 			 message
5975 			 ("Operands of %s are non-booleans (%t, %t): %s",
5976 			  lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5977 			 e1->loc);
5978 		    }
5979 		}
5980 	      else if (!ctype_isRealBool (te1))
5981 		{
5982 		  voptgenerror
5983 		    (FLG_BOOLOPS,
5984 		     message ("Left operand of %s is non-boolean (%t): %s",
5985 			      lltok_unparse (op), te1, exprNode_unparse (ret)),
5986 		     e1->loc);
5987 		}
5988 	      else if (!ctype_isRealBool (te2))
5989 		{
5990 		  voptgenerror
5991 		    (FLG_BOOLOPS,
5992 		     message ("Right operand of %s is non-boolean (%t): %s",
5993 			      lltok_unparse (op), te2, exprNode_unparse (ret)),
5994 		     e2->loc);
5995 		}
5996 	      else
5997 		{
5998 		  ;
5999 		}
6000 	    }
6001 	  tret = ctype_bool;
6002 	}
6003       break;
6004     default:
6005       llfatalbug
6006 	(cstring_makeLiteral
6007 	 ("There has been a problem in the parser. This is believed to result "
6008 	  "from a problem with bison v. 1.25.  Please try rebuidling Splint "
6009 	  "using the pre-compiled grammar files by commenting out the "
6010 	  "BISON= line in the top-level Makefile."));
6011     }
6012 
6013 skiprest:
6014   ret->typ = tret;
6015   DPRINTF (("Return type %s: %s", exprNode_unparse (ret), ctype_unparse (tret)));
6016 
6017   exprNode_checkUse (ret, e1->sref, e1->loc);
6018   exprNode_mergeUSs (ret, e2);
6019   exprNode_checkUse (ret, e2->sref, e2->loc);
6020 
6021   return ret;
6022 }
6023 
6024 /*@only@*/ exprNode
exprNode_op(exprNode e1,exprNode e2,lltok op)6025 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
6026 	     /*@only@*/ lltok op)
6027 {
6028   exprNode ret;
6029 
6030   checkMacroParen (e1);
6031   checkMacroParen (e2);
6032 
6033   if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
6034     {
6035       checkExpressionDefined (e1, e2, op);
6036     }
6037 
6038   ret = exprNode_makeOp (e1, e2, op);
6039   return (ret);
6040 }
6041 
6042 static
exprNode_checkAssignMod(exprNode e1,exprNode ret)6043 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
6044 {
6045   /*
6046   ** This is somewhat bogus!
6047   **
6048   ** Assigning to a nested observer in a non-observer datatype
6049   ** should not produce an error.
6050   */
6051 
6052   sRef ref = exprNode_getSref (e1);
6053 
6054   DPRINTF (("Check assign mod: %s",
6055 	    sRef_unparseFull (ref)));
6056 
6057   if (sRef_isObserver (ref)
6058       || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
6059 	  && ctype_isArray (ctype_realType (sRef_getType (ref)))))
6060     {
6061       sRef base = sRef_getBase (ref);
6062 
6063       if (sRef_isValid (base) && sRef_isObserver (base))
6064 	{
6065 	  exprNode_checkModify (e1, ret);
6066 	}
6067       else
6068 	{
6069 	  exprNode_checkModifyVal (e1, ret);
6070 	}
6071     }
6072   else
6073     {
6074       exprNode_checkModify (e1, ret);
6075     }
6076 }
6077 
6078 exprNode
exprNode_assign(exprNode e1,exprNode e2,lltok op)6079 exprNode_assign (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2, /*@only@*/ lltok op)
6080 {
6081   bool isalloc = FALSE;
6082   bool isjustalloc = FALSE;
6083   bool noalias = FALSE;
6084   exprNode ret;
6085 
6086   DPRINTF (("%s [%s] <- %s [%s]",
6087 	    exprNode_unparse (e1),
6088 	    ctype_unparse (e1->typ),
6089 	    exprNode_unparse (e2),
6090 	    ctype_unparse (e2->typ)));
6091 
6092   if (lltok_getTok (op) != TASSIGN)
6093     {
6094       ret = exprNode_makeOp (e1, e2, op);
6095 
6096       DPRINTF (("Here goes: %s %s",
6097 		ctype_unparse (e1->typ),
6098 		ctype_unparse (e2->typ)));
6099 
6100       if (exprNode_isDefined (e1)
6101 	  && exprNode_isDefined (e2))
6102 	{
6103 	  if (ctype_isNumeric (e2->typ)
6104 	      || ctype_isNumeric (e1->typ))
6105 	    {
6106 	      /* Its a pointer arithmetic expression like ptr += i */
6107 	      noalias = TRUE;
6108 	    }
6109 	}
6110     }
6111   else
6112     {
6113       ret = exprNode_createPartialCopy (e1);
6114       ret->kind = XPR_ASSIGN;
6115       ret->edata = exprData_makeOp (e1, e2, op);
6116 
6117       if (!exprNode_isError (e2))
6118 	{
6119 	  ret->sets = sRefSet_union (ret->sets, e2->sets);
6120 	  ret->msets = sRefSet_union (ret->msets, e2->msets);
6121 	  ret->uses = sRefSet_union (ret->uses, e2->uses);
6122 	}
6123     }
6124 
6125   checkExpressionDefined (e1, e2, op);
6126 
6127   if (exprNode_isError (e1))
6128     {
6129       if (!exprNode_isError (e2))
6130 	{
6131 	  ret->loc = fileloc_update (ret->loc, e2->loc);
6132 	}
6133       else
6134 	{
6135 	  ret->loc = fileloc_update (ret->loc, g_currentloc);
6136 	}
6137     }
6138 
6139   if (!exprNode_isError (e2))
6140     {
6141       checkMacroParen (e2);
6142     }
6143 
6144   if (exprNode_isDefined (e1))
6145     {
6146       if (sRef_isMacroParamRef (e1->sref))
6147 	{
6148 	  if (context_inIterDef ())
6149 	    {
6150 	      uentry ue = sRef_getUentry (e1->sref);
6151 
6152 	      if (uentry_isYield (ue))
6153 		{
6154 		  ;
6155 		}
6156 	      else
6157 		{
6158 		  if (fileloc_isDefined (e1->loc))
6159 		    {
6160 		      voptgenerror
6161 			(FLG_MACROPARAMS,
6162 			 message ("Assignment to non-yield iter parameter: %q",
6163 				  sRef_unparse (e1->sref)),
6164 			 e1->loc);
6165 		    }
6166 		  else
6167 		    {
6168 		      voptgenerror
6169 			(FLG_MACROPARAMS,
6170 			 message ("Assignment to non-yield iter parameter: %q",
6171 				  sRef_unparse (e1->sref)),
6172 			 g_currentloc);
6173 		    }
6174 		}
6175 	    }
6176 	  else
6177 	    {
6178 	      if (fileloc_isDefined (e1->loc))
6179 		{
6180 		  voptgenerror
6181 		    (FLG_MACROASSIGN,
6182 		     message ("Assignment to macro parameter: %q",
6183 			      sRef_unparse (e1->sref)),
6184 		     e1->loc);
6185 		}
6186 	      else
6187 		{
6188 		  voptgenerror
6189 		    (FLG_MACROASSIGN,
6190 		     message ("Assignment to macro parameter: %q",
6191 			      sRef_unparse (e1->sref)),
6192 		     g_currentloc);
6193 		}
6194 
6195 	      exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6196 	    }
6197 	}
6198       else
6199 	{
6200 	  exprNode_checkAssignMod (e1, ret);
6201 	}
6202 
6203       if (exprNode_isDefined (e2))
6204 	{
6205 	  if (lltok_getTok (op) == TASSIGN)
6206 	    {
6207 	      ctype te1 = exprNode_getType (e1);
6208 	      ctype te2 = exprNode_getType (e2);
6209 
6210 	      if (ctype_isVoid (te2))
6211 		{
6212 		  (void) gentypeerror
6213 		    (te2, e2, te1, e1,
6214 		     message ("Assignment of void value to %t: %s %s %s",
6215 			      te1, exprNode_unparse (e1),
6216 			      lltok_unparse (op),
6217 			      exprNode_unparse (e2)),
6218 		     e1->loc);
6219 		}
6220 	      else if (!ctype_forceMatch (te1, te2))
6221 		{
6222 		  if (exprNode_matchLiteral (te1, e2))
6223 		    {
6224 		      DPRINTF (("Literals match: %s / %s",
6225 				ctype_unparse (te1), exprNode_unparse (e2)));
6226 		      if (ctype_isNumAbstract (te1)) {
6227 			if (!context_flagOn (FLG_NUMABSTRACTLIT, e1->loc)) {
6228 			  (void) llgenhinterror
6229 			    (FLG_NUMABSTRACT,
6230 			     message
6231 			     ("Assignment of %t literal to numabstract type %t: %s %s %s",
6232 			      te2, te1,
6233 			      exprNode_unparse (e1),
6234 			      lltok_unparse (op),
6235 			      exprNode_unparse (e2)),
6236 			     cstring_makeLiteral
6237 			     ("Use +numabstractlit to allow numeric literals to be used as numabstract values"),
6238 			     e1->loc);
6239 			}
6240 		      }
6241 		    }
6242 		  else
6243 		    {
6244 		      (void) gentypeerror
6245 			(te2, e2, te1, e1,
6246 			 message ("Assignment of %t to %t: %s %s %s",
6247 				  te2, te1, exprNode_unparse (e1),
6248 				  lltok_unparse (op),
6249 				  exprNode_unparse (e2)),
6250 			 e1->loc);
6251 		    }
6252 		}
6253 	      else
6254 		{
6255 		  /* Type checks okay */
6256 		}
6257 	    }
6258 
6259 	  exprNode_mergeUSs (ret, e2);
6260 	  exprNode_checkUse (ret, e2->sref, e2->loc);
6261 
6262 	  DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6263 	  if (noalias)
6264 	    {
6265 	      ;
6266 	    }
6267 	  else
6268 	    {
6269 	      doAssign (e1, e2, FALSE);
6270 	    }
6271 
6272 	  ret->sref = e1->sref;
6273 	}
6274       else
6275 	{
6276 	  if (exprNode_isDefined (e2))
6277 	    {
6278 	      exprNode_mergeUSs (ret, e2);
6279 	      exprNode_checkUse (ret, e2->sref, e2->loc);
6280 	    }
6281 	}
6282 
6283       if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6284 	{
6285 	  exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6286 	}
6287 
6288       isjustalloc = sRef_isJustAllocated (e1->sref);
6289       isalloc = sRef_isAllocated (e1->sref);
6290 
6291       if (sRef_isField (e1->sref))
6292 	{
6293 	  sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6294 
6295 	  if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6296 	    {
6297 	      exprNode_checkUse (ret, root, e1->loc);
6298 	    }
6299 
6300 	}
6301 
6302       /*
6303       ** be careful!  this defines e1->sref.
6304       */
6305 
6306       /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6307 
6308       DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6309       exprNode_checkSet (ret, e1->sref);
6310 
6311       if (isjustalloc)
6312 	{
6313 	  sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6314 				     ? e2->loc : e1->loc);
6315 	}
6316       else
6317 	{
6318 	  if (isalloc)
6319 	    {
6320 	      sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6321 	    }
6322 	}
6323     }
6324 
6325   return ret;
6326 }
6327 
6328 exprNode
exprNode_cond(exprNode pred,exprNode ifclause,exprNode elseclause)6329 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6330 	       /*@keep@*/ exprNode elseclause)
6331 {
6332   exprNode ret;
6333 
6334   if (!exprNode_isError (pred))
6335     {
6336       ret = exprNode_createPartialCopy (pred);
6337       checkMacroParen (pred);
6338       exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6339 
6340       if (!exprNode_isError (ifclause))
6341 	{
6342 	  checkMacroParen (ifclause);   /* update macro counts! */
6343 
6344 	  if (!exprNode_isError (elseclause))
6345 	    {
6346 	      checkMacroParen (elseclause);
6347 
6348 	      if (!exprNode_matchTypes (ifclause, elseclause))
6349 		{
6350 		  if (gentypeerror
6351 		      (exprNode_getType (ifclause),
6352 		       ifclause,
6353 		       exprNode_getType (elseclause),
6354 		       elseclause,
6355 		       message ("Conditional clauses are not of same type: "
6356 				"%s (%t), %s (%t)",
6357 				exprNode_unparse (ifclause),
6358 				exprNode_getType (ifclause),
6359 				exprNode_unparse (elseclause),
6360 				exprNode_getType (elseclause)),
6361 		       ifclause->loc))
6362 		    {
6363 		      ret->sref = sRef_undefined;
6364 		      ret->typ = ctype_unknown;
6365 		    }
6366 		}
6367 	      else
6368 		{
6369 		  /* for now...should merge the states */
6370 		  ret->sref = ifclause->sref;
6371 		  ret->typ = ifclause->typ;
6372 
6373 		  if (exprNode_isNullValue (ifclause))
6374 		    {
6375 		      ret->typ = elseclause->typ;
6376 		    }
6377 		}
6378 
6379 	      exprNode_checkUse (ret, pred->sref, pred->loc);
6380 	      exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6381 	      exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6382 
6383 	      exprNode_mergeCondUSs (ret, ifclause, elseclause);
6384 
6385 	    }
6386 	  else
6387 	    {
6388 	      ret->typ = ifclause->typ;
6389 
6390 	      exprNode_checkUse (pred, pred->sref, pred->loc);
6391 	      exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6392 
6393 	      exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6394 	    }
6395 	}
6396       else
6397 	{
6398 	  if (!exprNode_isError (elseclause))
6399 	    {
6400 	      ret->typ = elseclause->typ;
6401 
6402 	      exprNode_checkUse (pred, pred->sref, pred->loc);
6403 	      exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6404 
6405 	      exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6406 	    }
6407 	}
6408     }
6409   else /* pred is error */
6410     {
6411       if (!exprNode_isError (ifclause))
6412 	{
6413 	  ret = exprNode_createSemiCopy (ifclause);
6414 
6415 	  checkMacroParen (ifclause);   /* update macro counts! */
6416 
6417 	  if (!exprNode_isError (elseclause))
6418 	    {
6419 	      checkMacroParen (elseclause);
6420 
6421 	      ret->typ = ifclause->typ;
6422 
6423 	      if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6424 		{
6425 		  if (gentypeerror
6426 		      (exprNode_getType (ifclause),
6427 		       ifclause,
6428 		       exprNode_getType (elseclause),
6429 		       elseclause,
6430 		       message ("Conditional clauses are not of same type: "
6431 				"%s (%t), %s (%t)",
6432 				exprNode_unparse (ifclause),
6433 				exprNode_getType (ifclause),
6434 				exprNode_unparse (elseclause),
6435 				exprNode_getType (elseclause)),
6436 		       ifclause->loc))
6437 		    {
6438 		      ret->typ = ctype_unknown;
6439 		    }
6440 		}
6441 
6442 	      exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6443 	      exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6444 
6445 	      exprNode_mergeCondUSs (ret, ifclause, elseclause);
6446 	    }
6447 	}
6448       else if (!exprNode_isError (elseclause)) /* pred, if errors */
6449 	{
6450 	  ret = exprNode_createSemiCopy (ifclause);
6451 
6452 	  ret->typ = elseclause->typ;
6453 	  checkMacroParen (elseclause);
6454 
6455 	  exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6456 	  exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6457 	}
6458       else /* all errors! */
6459 	{
6460 	  ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6461 	}
6462     }
6463 
6464   ret->kind = XPR_COND;
6465   ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6466 
6467   if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6468     {
6469       exprNode_combineControl (ret, ifclause, elseclause);
6470     }
6471 
6472   return (ret);
6473 }
6474 
6475 exprNode
exprNode_condIfOmit(exprNode pred,exprNode elseclause)6476 exprNode_condIfOmit (/*@keep@*/ exprNode pred,
6477 		     /*@keep@*/ exprNode elseclause)
6478 {
6479   exprNode ifclause = exprNode_createPartialCopy (pred);
6480 
6481   if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (pred)))
6482     {
6483       (void) llgenhinterror
6484 	(FLG_SYNTAX,
6485 	 message ("Conditionals with Omitted Operands is not supported by ISO C99"),
6486 	 message ("Use +gnuextensions to allow compound statement "
6487 		  "expressions (and other GNU language extensions) "
6488 		  "without this warning"),
6489 	 exprNode_loc (pred));
6490     }
6491 
6492   return exprNode_cond(pred, ifclause, elseclause);
6493 }
6494 
6495 exprNode
exprNode_vaArg(lltok tok,exprNode arg,qtype qt)6496 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6497 {
6498   ctype totype = qtype_getType (qt);
6499   exprNode ret =
6500     exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6501   ctype targ;
6502 
6503   /*
6504   ** check use of va_arg : <valist>, type -> type
6505   */
6506 
6507   if (exprNode_isError (arg))
6508     {
6509     }
6510   else
6511     {
6512       targ = exprNode_getType (arg);
6513 
6514       /*
6515       ** arg should have be a pointer
6516       */
6517 
6518       if (!ctype_isUA (targ) ||
6519 	  (!typeId_equal (ctype_typeId (targ),
6520 			  usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6521 	{
6522 	  voptgenerror
6523 	    (FLG_TYPE,
6524 	     message ("First argument to va_arg is not a va_list (type %t): %s",
6525 		      targ, exprNode_unparse (arg)),
6526 	     arg->loc);
6527 	}
6528 
6529       exprNode_checkSet (ret, arg->sref);
6530     }
6531 
6532   /*
6533   ** return type is totype
6534   */
6535 
6536   ret->typ = totype;
6537   ret->kind = XPR_VAARG;
6538   ret->edata = exprData_makeCast (tok, arg, qt);
6539 
6540   return (ret);
6541 }
6542 
exprNode_labelMarker(cstring label)6543 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6544 {
6545   exprNode ret = exprNode_createPlain (ctype_undefined);
6546   ret->kind = XPR_LABEL;
6547   ret->edata = exprData_makeLiteral (label);
6548   ret->isJumpPoint = TRUE;
6549 
6550   return (ret); /* for now, ignore label */
6551 }
6552 
exprNode_notReached(exprNode stmt)6553 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6554 {
6555   if (exprNode_isDefined (stmt))
6556     {
6557       stmt->isJumpPoint = TRUE;
6558 
6559       /* This prevent stray no return path errors, etc. */
6560       stmt->exitCode = XK_MUSTEXIT;
6561     }
6562 
6563   return (stmt);
6564 }
6565 
exprNode_isDefaultMarker(exprNode e)6566 bool exprNode_isDefaultMarker (exprNode e)
6567 {
6568   if (exprNode_isDefined (e))
6569     {
6570       return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6571     }
6572 
6573   return FALSE;
6574 }
6575 
exprNode_isCaseMarker(exprNode e)6576 bool exprNode_isCaseMarker (exprNode e)
6577 {
6578   if (exprNode_isDefined (e))
6579     {
6580       return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6581     }
6582 
6583   return FALSE;
6584 }
6585 
exprNode_isLabelMarker(exprNode e)6586 bool exprNode_isLabelMarker (exprNode e)
6587 {
6588   if (exprNode_isDefined (e))
6589     {
6590       return (e->kind == XPR_LABEL);
6591     }
6592 
6593   return FALSE;
6594 }
6595 
exprNode_caseMarker(exprNode test,bool fallThrough)6596 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6597 {
6598   exprNode ret = exprNode_createPartialCopy (test);
6599 
6600   ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6601 
6602   if (exprNode_isError (test)) {
6603     return ret;
6604   }
6605 
6606   exprNode_checkUse (ret, test->sref, test->loc);
6607 
6608   usymtab_setExitCode (ret->exitCode);
6609 
6610   if (ret->mustBreak)
6611     {
6612       usymtab_setMustBreak ();
6613     }
6614 
6615   ret->edata = exprData_makeSingle (test);
6616   ret->isJumpPoint = TRUE;
6617 
6618   return ret;
6619 }
6620 
6621 # if 0
6622 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6623 {
6624   exprNode ret = exprNode_createPartialCopy (test);
6625 
6626   ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6627   ret->edata = exprData_makePair (test, stmt);
6628   ret->isJumpPoint = TRUE;
6629 
6630   if (exprNode_isError (test))
6631     {
6632       return ret;
6633     }
6634 
6635   exprNode_checkUse (ret, test->sref, test->loc);
6636 
6637   if (exprNode_isError (stmt))
6638     {
6639       return ret;
6640     }
6641 
6642   exprNode_mergeUSs (ret, stmt);
6643 
6644   ret->exitCode = stmt->exitCode;
6645   ret->mustBreak = stmt->mustBreak;
6646   ret->canBreak = stmt->canBreak;
6647 
6648   usymtab_setExitCode (ret->exitCode);
6649 
6650   if (ret->mustBreak)
6651     {
6652       usymtab_setMustBreak ();
6653     }
6654 
6655   return ret;
6656 }
6657 # endif
6658 
6659 /*@notnull@*/ /*@only@*/ exprNode
exprNode_defaultMarker(lltok def,bool fallThrough)6660 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6661 {
6662   exprNode ret = exprNode_createTok (def);
6663 
6664   ret->isJumpPoint = TRUE;
6665   ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6666   return (ret);
6667 }
6668 
6669 bool
exprNode_mayEscape(exprNode e)6670 exprNode_mayEscape (exprNode e)
6671 {
6672   if (exprNode_isDefined (e))
6673     {
6674       return exitkind_couldEscape (e->exitCode);
6675     }
6676   return FALSE;
6677 }
6678 
6679 static bool
exprNode_mustBreak(exprNode e)6680 exprNode_mustBreak (exprNode e)
6681 {
6682   if (exprNode_isDefined (e))
6683     {
6684       return e->mustBreak;
6685     }
6686 
6687   return FALSE;
6688 }
6689 
6690 bool
exprNode_mustEscape(exprNode e)6691 exprNode_mustEscape (exprNode e)
6692 {
6693   if (exprNode_isDefined (e))
6694     {
6695       return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6696     }
6697 
6698   return FALSE;
6699 }
6700 
6701 bool
exprNode_errorEscape(exprNode e)6702 exprNode_errorEscape (exprNode e)
6703 {
6704   if (exprNode_isDefined (e))
6705     {
6706       return exitkind_isError (e->exitCode);
6707     }
6708 
6709   return FALSE;
6710 }
6711 
exprNode_concat(exprNode e1,exprNode e2)6712 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6713 {
6714   exprNode ret = exprNode_createPartialCopy (e1);
6715 
6716   DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6717 
6718   ret->edata = exprData_makePair (e1, e2);
6719   ret->kind = XPR_STMTLIST;
6720 
6721   if (exprNode_isDefined (e1))
6722     {
6723       ret->isJumpPoint = e1->isJumpPoint;
6724       ret->canBreak = e1->canBreak;
6725     }
6726   else
6727     {
6728       if (exprNode_isDefined (e2))
6729 	{
6730 	  ret->loc = fileloc_update (ret->loc, e2->loc);
6731 	}
6732     }
6733 
6734   if (exprNode_isDefined (e2))
6735     {
6736       ret->exitCode = e2->exitCode;
6737       ret->mustBreak = e2->mustBreak;
6738       if (e2->canBreak) ret->canBreak = TRUE;
6739     }
6740 
6741   /*
6742   ** if e1 must return, then e2 is unreachable!
6743   */
6744 
6745   if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6746     {
6747       if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6748 	  && !(e2->isJumpPoint))
6749 	{
6750 	  if (context_getFlag (FLG_UNREACHABLE))
6751 	    {
6752 	      exprNode nr = e2;
6753 
6754 	      if (e2->kind == XPR_STMT)
6755 		{
6756 		  nr = exprData_getUopNode (e2->edata);
6757 		}
6758 
6759 	      if ((nr->kind == XPR_TOK
6760 		   && lltok_isSemi (exprData_getTok (nr->edata))))
6761 		{
6762 		  /* okay to have unreachable ";" */
6763 		  ret->exitCode = XK_MUSTEXIT;
6764 		  ret->canBreak = TRUE;
6765 		}
6766 	      else
6767 		{
6768 		  if (optgenerror (FLG_UNREACHABLE,
6769 				   message ("Unreachable code: %s",
6770 					    exprNode_unparseFirst (nr)),
6771 				   exprNode_loc (nr)))
6772 		    {
6773 		      ret->isJumpPoint = TRUE;
6774 		      ret->mustBreak = FALSE;
6775 		      ret->exitCode = XK_ERROR;
6776 		      DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6777 		    }
6778 		  else
6779 		    {
6780 		      ret->exitCode = XK_MUSTEXIT;
6781 		      ret->canBreak = TRUE;
6782 		    }
6783 
6784 		}
6785 	    }
6786 	}
6787       else
6788 	{
6789 	  if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6790 	    {
6791 	      /*
6792               ** We want a warning anytime we have:
6793 	      **         case xxx: ...
6794 	      **                   yyy;  <<<- no break or return
6795 	      **         case zzz: ...
6796 	      */
6797 
6798 	      exprNode lastStmt = exprNode_lastStatement (e1);
6799 
6800 	      if (exprNode_isDefined (lastStmt)
6801 		  && !exprNode_mustEscape (lastStmt)
6802 		  && !exprNode_mustBreak (lastStmt)
6803 		  && !exprNode_isCaseMarker (lastStmt)
6804 		  && !exprNode_isDefaultMarker (lastStmt)
6805 		  && !exprNode_isLabelMarker (lastStmt))
6806 		{
6807 		  voptgenerror (FLG_CASEBREAK,
6808 				cstring_makeLiteral
6809 				("Fall through case (no preceding break)"),
6810 				e2->loc);
6811 		}
6812 	    }
6813 	}
6814     }
6815 
6816   exprNode_mergeUSs (ret, e2);
6817 
6818   usymtab_setExitCode (ret->exitCode);
6819 
6820   if (ret->mustBreak)
6821     {
6822       usymtab_setMustBreak ();
6823     }
6824 
6825   DPRINTF (("==> %s", exprNode_unparse (ret)));
6826   return ret;
6827 }
6828 
exprNode_createTok(lltok t)6829 exprNode exprNode_createTok (/*@only@*/ lltok t)
6830 {
6831   exprNode ret = exprNode_create (ctype_unknown);
6832   ret->kind = XPR_TOK;
6833   ret->edata = exprData_makeTok (t);
6834   return ret;
6835 }
6836 
exprNode_statement(exprNode e,lltok t)6837 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6838 {
6839   if (!exprNode_isError (e))
6840     {
6841       exprChecks_checkStatementEffect(e);
6842     }
6843 
6844   return (exprNode_statementError (e, t));
6845 }
6846 
exprNode_statementError(exprNode e,lltok t)6847 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6848 {
6849   exprNode ret = exprNode_createPartialCopy (e);
6850 
6851   if (!exprNode_isError (e))
6852     {
6853       if (e->kind != XPR_ASSIGN)
6854 	{
6855 	  exprNode_checkUse (ret, e->sref, e->loc);
6856 	}
6857 
6858       ret->exitCode = e->exitCode;
6859       ret->canBreak = e->canBreak;
6860       ret->mustBreak = e->mustBreak;
6861     }
6862 
6863   ret->edata = exprData_makeUop (e, t);
6864   ret->kind = XPR_STMT;
6865 
6866   return ret;
6867 }
6868 
exprNode_checkExpr(exprNode e)6869 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6870 {
6871   if (!exprNode_isError (e))
6872     {
6873       if (e->kind != XPR_ASSIGN)
6874 	{
6875 	  exprNode_checkUse (e, e->sref, e->loc);
6876 	}
6877     }
6878 
6879   return e;
6880 }
6881 
exprNode_produceGuards(exprNode pred)6882 void exprNode_produceGuards (exprNode pred)
6883 {
6884   if (!exprNode_isError (pred))
6885     {
6886       if (ctype_isRealPointer (pred->typ))
6887 	{
6888 	  pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6889 	}
6890 
6891       exprNode_checkUse (pred, pred->sref, pred->loc);
6892       exprNode_resetSref (pred);
6893     }
6894 }
6895 
exprNode_compoundStatementExpression(lltok tlparen,exprNode e)6896 exprNode exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen, /*@only@*/ exprNode e)
6897 {
6898   exprNode laststmt;
6899 
6900   DPRINTF (("Compound: %s", exprNode_unparse (e)));
6901 
6902   if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (e)))
6903     {
6904       (void) llgenhinterror
6905 	(FLG_SYNTAX,
6906 	 message ("Compound statement expressions is not supported by ISO C99"),
6907 	 message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) "
6908 		  "without this warning"),
6909 	 exprNode_loc (e));
6910     }
6911 
6912   /*
6913   ** The type of a compoundStatementExpression is the type of the last statement
6914   */
6915 
6916   llassert (exprNode_isBlock (e));
6917   laststmt = exprNode_lastStatement (e);
6918 
6919   DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt), ctype_unparse (exprNode_getType (laststmt))));
6920   DPRINTF (("e: %s", exprNode_unparse (e)));
6921   e->typ = exprNode_getType (laststmt);
6922   return exprNode_addParens (tlparen, e);
6923 }
6924 
6925 
exprNode_makeBlock(exprNode e)6926 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6927 {
6928   exprNode ret = exprNode_createPartialCopy (e);
6929 
6930   if (!exprNode_isError (e))
6931     {
6932       ret->exitCode = e->exitCode;
6933       ret->canBreak = e->canBreak;
6934       ret->mustBreak = e->mustBreak;
6935     }
6936 
6937   DPRINTF (("Block e: %s", exprNode_unparse (e)));
6938   ret->edata = exprData_makeSingle (e);
6939   ret->kind = XPR_BLOCK;
6940   DPRINTF (("Block: %s", exprNode_unparse (ret)));
6941   return ret;
6942 }
6943 
exprNode_isBlock(exprNode e)6944 bool exprNode_isBlock (exprNode e)
6945 {
6946   return (exprNode_isDefined (e)
6947 	  && ((e)->kind == XPR_BLOCK));
6948 }
6949 
exprNode_isStatement(exprNode e)6950 bool exprNode_isStatement (exprNode e)
6951 {
6952   return (exprNode_isDefined (e)
6953 	  && ((e)->kind == XPR_STMT));
6954 }
6955 
exprNode_isAssign(exprNode e)6956 bool exprNode_isAssign (exprNode e)
6957 {
6958   if (exprNode_isDefined (e))
6959     {
6960       return (e->kind == XPR_ASSIGN);
6961     }
6962 
6963   return FALSE;
6964 }
6965 
exprNode_isEmptyStatement(exprNode e)6966 bool exprNode_isEmptyStatement (exprNode e)
6967 {
6968   return (exprNode_isDefined (e)
6969 	  && (e->kind == XPR_TOK)
6970 	  && (lltok_isSemi (exprData_getTok (e->edata))));
6971 }
6972 
exprNode_isMultiStatement(exprNode e)6973 bool exprNode_isMultiStatement (exprNode e)
6974 {
6975   return (exprNode_isDefined (e)
6976 	  && ((e->kind == XPR_FOR)
6977 	      || (e->kind == XPR_FORPRED)
6978 	      || (e->kind == XPR_IF)
6979 	      || (e->kind == XPR_IFELSE)
6980 	      || (e->kind == XPR_WHILE)
6981 	      || (e->kind == XPR_WHILEPRED)
6982 	      || (e->kind == XPR_DOWHILE)
6983 	      || (e->kind == XPR_BLOCK)
6984 	      || (e->kind == XPR_STMT)
6985 	      || (e->kind == XPR_STMTLIST)
6986 	      || (e->kind == XPR_SWITCH)));
6987 }
6988 
exprNode_checkIfPred(exprNode pred)6989 void exprNode_checkIfPred (exprNode pred)
6990 {
6991   exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6992 }
6993 
exprNode_if(exprNode pred,exprNode tclause)6994 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6995 {
6996   exprNode ret;
6997   bool emptyErr = FALSE;
6998 
6999   if (context_maybeSet (FLG_IFEMPTY))
7000     {
7001       if (exprNode_isEmptyStatement (tclause))
7002 	{
7003 	  emptyErr = optgenerror (FLG_IFEMPTY,
7004 				  cstring_makeLiteral
7005 				  ("Body of if statement is empty"),
7006 				  exprNode_loc (tclause));
7007 	}
7008     }
7009 
7010   if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
7011     {
7012       if (exprNode_isDefined (tclause)
7013 	  && !exprNode_isBlock (tclause))
7014 	{
7015 	  voptgenerror (FLG_IFBLOCK,
7016 			message
7017 			("Body of if statement is not a block: %s",
7018 			 exprNode_unparse (tclause)),
7019 			exprNode_loc (tclause));
7020 	}
7021     }
7022 
7023   if (exprNode_isError (pred))
7024     {
7025       if (exprNode_isError (tclause))
7026 	{
7027 	  ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7028 	}
7029       else
7030 	{
7031 	  ret = exprNode_createPartialCopy (tclause);
7032 	}
7033     }
7034   else
7035     {
7036       if (exprNode_mustEscape (pred))
7037 	{
7038 	  voptgenerror
7039 	    (FLG_UNREACHABLE,
7040 	     message ("Predicate always exits: %s", exprNode_unparse (pred)),
7041 	     exprNode_loc (pred));
7042 	}
7043 
7044       exprNode_checkUse (pred, pred->sref, pred->loc);
7045 
7046       if (!exprNode_isError (tclause))
7047 	{
7048 	  exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
7049 	}
7050 
7051       ret = exprNode_createPartialCopy (pred);
7052     }
7053 
7054   ret->kind = XPR_IF;
7055   ret->edata = exprData_makePair (pred, tclause);
7056 
7057   ret->exitCode = XK_UNKNOWN;
7058 
7059   if (exprNode_isDefined (tclause))
7060     {
7061       ret->exitCode = exitkind_makeConditional (tclause->exitCode);
7062       ret->canBreak = tclause->canBreak;
7063       ret->sets = sRefSet_union (ret->sets, tclause->sets);
7064       ret->msets = sRefSet_union (ret->msets, tclause->msets);
7065       ret->uses = sRefSet_union (ret->uses, tclause->uses);
7066     }
7067 
7068   ret->mustBreak = FALSE;
7069 
7070   return ret;
7071 }
7072 
exprNode_ifelse(exprNode pred,exprNode tclause,exprNode eclause)7073 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
7074 			  /*@only@*/ exprNode tclause,
7075 			  /*@only@*/ exprNode eclause)
7076 {
7077   exprNode ret;
7078   bool tEmptyErr = FALSE;
7079   bool eEmptyErr = FALSE;
7080 
7081   if (context_maybeSet (FLG_IFEMPTY))
7082     {
7083       if (exprNode_isEmptyStatement (tclause))
7084 	{
7085 	  tEmptyErr = optgenerror
7086 	    (FLG_IFEMPTY,
7087 	     cstring_makeLiteral
7088 	     ("Body of if clause of if statement is empty"),
7089 	     exprNode_loc (tclause));
7090 	}
7091 
7092       if (exprNode_isEmptyStatement (eclause))
7093 	{
7094 	  eEmptyErr = optgenerror
7095 	    (FLG_IFEMPTY,
7096 	     cstring_makeLiteral
7097 	     ("Body of else clause of if statement is empty"),
7098 	     exprNode_loc (eclause));
7099 	}
7100     }
7101 
7102   if (context_maybeSet (FLG_IFBLOCK))
7103     {
7104       if (!tEmptyErr
7105 	  && exprNode_isDefined (tclause)
7106 	  && !exprNode_isBlock (tclause))
7107 	{
7108 	  voptgenerror (FLG_IFBLOCK,
7109 			message
7110 			("Body of if clause of if statement is not a block: %s",
7111 			 exprNode_unparse (tclause)),
7112 			exprNode_loc (tclause));
7113 	}
7114 
7115       if (!eEmptyErr
7116 	  && exprNode_isDefined (eclause)
7117 	  && !exprNode_isBlock (eclause)
7118 	  && !(eclause->kind == XPR_IF)
7119 	  && !(eclause->kind == XPR_IFELSE))
7120 	{
7121 	  voptgenerror
7122 	    (FLG_IFBLOCK,
7123 	     message
7124 	     ("Body of else clause of if statement is not a block: %s",
7125 	      exprNode_unparse (eclause)),
7126 	     exprNode_loc (eclause));
7127 	}
7128     }
7129 
7130   if (context_maybeSet (FLG_ELSEIFCOMPLETE))
7131     {
7132       if (exprNode_isDefined (eclause)
7133 	  && (eclause->kind == XPR_IF))
7134 	{
7135 	  voptgenerror (FLG_ELSEIFCOMPLETE,
7136 			message ("Incomplete else if logic (no final else): %s",
7137 				 exprNode_unparse (eclause)),
7138 			exprNode_loc (eclause));
7139 	}
7140     }
7141 
7142   if (exprNode_isError (pred))
7143     {
7144       if (exprNode_isError (tclause))
7145 	{
7146 	  if (exprNode_isError (eclause))
7147 	    {
7148 	      ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7149 	    }
7150 	  else
7151 	    {
7152 	      ret = exprNode_createPartialCopy (eclause);
7153 	    }
7154 	}
7155       else
7156 	{
7157 	  ret = exprNode_createPartialCopy (tclause);
7158 	}
7159     }
7160   else /* pred is okay */
7161     {
7162       ret = exprNode_createPartialCopy (pred);
7163 
7164       if (exprNode_mustEscape (pred))
7165 	{
7166 	  voptgenerror
7167 	    (FLG_UNREACHABLE,
7168 	     message ("Predicate always exits: %s", exprNode_unparse (pred)),
7169 	     exprNode_loc (pred));
7170 	}
7171 
7172       exprNode_checkUse (ret, pred->sref, pred->loc);
7173       exprNode_mergeCondUSs (ret, tclause, eclause);
7174     }
7175 
7176   ret->kind = XPR_IFELSE;
7177   ret->edata = exprData_makeCond (pred, tclause, eclause);
7178 
7179   if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
7180     {
7181       exprNode_combineControl (ret, tclause, eclause);
7182       ret->loc = fileloc_update (ret->loc, eclause->loc);
7183     }
7184 
7185   return ret;
7186 }
7187 
7188 /*
7189 ** *allpaths <- TRUE iff all executions paths must go through the switch
7190 */
7191 
7192 static bool
checkSwitchExpr(exprNode test,exprNode e,bool * allpaths)7193 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7194 {
7195   exprNodeSList el = exprNode_flatten (e);
7196   bool mustReturn = TRUE; /* find a branch that doesn't */
7197   bool thisReturn = FALSE;
7198   bool hasDefault = FALSE;
7199   bool hasAllMembers = FALSE;
7200   bool inSwitch = FALSE;
7201   bool isEnumSwitch = FALSE;
7202   bool canBreak = FALSE;
7203   bool fallThrough = FALSE;
7204   ctype ct = ctype_unknown;
7205   enumNameSList usedEnums;
7206   enumNameList enums;
7207 
7208   if (exprNode_isDefined (test))
7209     {
7210       ctype ttype;
7211 
7212       ct = test->typ;
7213       ttype = ctype_realType (ct);
7214 
7215       if (ctype_isEnum (ttype))
7216 	{
7217 	  isEnumSwitch = TRUE;
7218 	  enums = ctype_elist (ttype);
7219 	  usedEnums = enumNameSList_new ();
7220 	}
7221     }
7222 
7223   exprNodeSList_elements (el, current)
7224     {
7225 
7226       DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
7227 
7228       if (exprNode_isDefined (current))
7229 	{
7230 	  switch (current->kind)
7231 	    {
7232 	    case XPR_FTDEFAULT:
7233 	    case XPR_DEFAULT:
7234 	      if (hasDefault)
7235 		{
7236 		  voptgenerror
7237 		    (FLG_DUPLICATECASES,
7238 		     message ("Duplicate default cases in switch"),
7239 		     exprNode_loc (current));
7240 		}
7241 	    /*@fallthrough@*/
7242 	    case XPR_FTCASE:
7243 	    case XPR_CASE:
7244 	      if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7245 		{
7246 		  hasDefault = TRUE;
7247 		}
7248 	      else
7249 		{
7250 		  if (isEnumSwitch)
7251 		    {
7252 		      exprNode st = exprData_getSingle (current->edata);
7253 		      uentry ue = exprNode_getUentry (st);
7254 
7255 		      if (uentry_isValid (ue))
7256 			{
7257 			  cstring cname = uentry_rawName (ue);
7258 
7259 			  if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7260 			    {
7261 			      if (enumNameSList_member
7262 				  (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7263 				{
7264 				  voptgenerror
7265 				    (FLG_DUPLICATECASES,
7266 				     message ("Duplicate case in switch: %s",
7267 					      cname),
7268 				     current->loc);
7269 				}
7270 			      else
7271 				{
7272 				  enumNameSList_addh (usedEnums, cname);
7273 				}
7274 			    }
7275 			  else
7276 			    {
7277 			      voptgenerror
7278 				(FLG_TYPE,
7279 				 message ("Case in switch not %s member: %s",
7280 					  ctype_unparse (ct), cname),
7281 				 current->loc);
7282 			    }
7283 			}
7284 		    }
7285 		}
7286 
7287 	      if (inSwitch && !fallThrough)
7288 		{
7289 		  if (!thisReturn || canBreak)
7290 		    {
7291 		      mustReturn = FALSE;
7292 		    }
7293 		}
7294 
7295 	      fallThrough = TRUE;
7296 	      inSwitch = TRUE;
7297 	      thisReturn = FALSE;
7298 	      canBreak = FALSE;
7299 	      /*@switchbreak@*/ break;
7300 	    default:
7301 	      thisReturn = thisReturn || exprNode_mustEscape (current);
7302 	      canBreak = canBreak || current->canBreak;
7303 	      if (canBreak) fallThrough = FALSE;
7304 	    }
7305 	}
7306     } end_exprNodeSList_elements;
7307 
7308   if (inSwitch) /* check the last one! */
7309     {
7310       if (!thisReturn || canBreak)
7311 	{
7312 	  mustReturn = FALSE;
7313 	}
7314     }
7315 
7316   if (isEnumSwitch)
7317     {
7318       if (!hasDefault
7319 	  && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7320 	      enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7321 	{
7322 	  enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7323 
7324 	  voptgenerror (FLG_MISSCASE,
7325 			message ("Missing case%s in switch: %q",
7326 				 cstring_makeLiteralTemp
7327 				 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7328 				 enumNameSList_unparse (unused)),
7329 			g_currentloc);
7330 
7331 	  enumNameSList_free (unused);
7332 	  *allpaths = FALSE; /* evans 2002-01-01 */
7333 	}
7334       else
7335 	{
7336 	  hasAllMembers = TRUE;
7337 	  *allpaths = TRUE;
7338 	}
7339 
7340       enumNameSList_free (usedEnums);
7341     }
7342   else
7343     {
7344       *allpaths = hasDefault;
7345     }
7346 
7347   exprNodeSList_free (el);
7348   return ((hasDefault || hasAllMembers) && mustReturn);
7349 }
7350 
exprNode_switch(exprNode e,exprNode s)7351 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7352 {
7353   exprNode ret = exprNode_createPartialCopy (e);
7354   bool allpaths;
7355 
7356   DPRINTF (("Switch: %s", exprNode_unparse (s)));
7357 
7358   ret->kind = XPR_SWITCH;
7359   ret->edata = exprData_makePair (e, s);
7360 
7361   if (!exprNode_isError (s))
7362     {
7363       exprNode fs = exprNode_firstStatement (s);
7364       ret->loc = fileloc_update (ret->loc, s->loc);
7365 
7366       if (exprNode_isUndefined (fs)
7367 	  || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7368 	  || exprNode_isDefaultMarker (fs)) {
7369 	;
7370       } else {
7371 	voptgenerror (FLG_FIRSTCASE,
7372 		      message
7373 		      ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7374 		      fs->loc);
7375       }
7376     }
7377 
7378   if (!exprNode_isError (e))
7379     {
7380       if (checkSwitchExpr (e, s, &allpaths))
7381 	{
7382 	  ret->exitCode = XK_MUSTRETURN;
7383 	}
7384       else
7385 	{
7386 	  ret->exitCode = e->exitCode;
7387 	}
7388 
7389       ret->canBreak = e->canBreak;
7390       ret->mustBreak = e->mustBreak;
7391     }
7392   /*
7393   ** forgot this!
7394   **   exprNode.c:3883,32: Variable allpaths used before definition
7395   */
7396   else
7397     {
7398       allpaths = FALSE;
7399     }
7400 
7401   DPRINTF (("Context exit switch!"));
7402   context_exitSwitch (ret, allpaths);
7403   DPRINTF (("Context exit switch done!"));
7404 
7405   return ret;
7406 }
7407 
checkInfiniteLoop(exprNode test,exprNode body)7408 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7409 			       /*@notnull@*/ exprNode body)
7410 {
7411   sRefSet tuses = test->uses;
7412 
7413   if (!sRefSet_isEmpty (test->uses))
7414     {
7415       sRefSet sets = sRefSet_newCopy (body->sets);
7416       bool hasError = TRUE;
7417       bool innerState = FALSE;
7418       sRefSet tuncon = sRefSet_undefined;
7419 
7420       sets = sRefSet_union (sets, test->sets);
7421       sets = sRefSet_union (sets, body->msets);
7422       sets = sRefSet_union (sets, test->msets);
7423 
7424       sRefSet_allElements (tuses, el)
7425 	{
7426 	  if (sRef_isUnconstrained (el))
7427 	    {
7428 	      tuncon = sRefSet_insert (tuncon, el);
7429 	    }
7430 	  else
7431 	    {
7432 	      if (sRefSet_member (sets, el))
7433 		{
7434 		  hasError = FALSE;
7435 		  break;
7436 		}
7437 	    }
7438 
7439 	  if (sRef_isInternalState (el)
7440 	      || sRef_isFileStatic (sRef_getRootBase (el)))
7441 	    {
7442 	      innerState = TRUE;
7443 	    }
7444 	} end_sRefSet_allElements ;
7445 
7446       if (hasError)
7447 	{
7448 	  sRefSet suncon = sRefSet_undefined;
7449 	  bool sinner = FALSE;
7450 
7451 	  sRefSet_allElements (sets, el)
7452 	    {
7453 	      if (sRef_isUnconstrained (el))
7454 		{
7455 		  suncon = sRefSet_insert (suncon, el);
7456 		}
7457 	      else if (sRef_isInternalState (el))
7458 		{
7459 		  sinner = TRUE;
7460 		}
7461 	      else
7462 		{
7463 		  ;
7464 		}
7465 	    } end_sRefSet_allElements ;
7466 
7467 	  if (sinner && innerState)
7468 	    {
7469 	      ;
7470 	    }
7471 	  else if (sRefSet_isEmpty (tuncon)
7472 		   && sRefSet_isEmpty (suncon))
7473 	    {
7474 	      voptgenerror
7475 		(FLG_INFLOOPS,
7476 		 message
7477 		 ("Suspected infinite loop.  No value used in loop test (%q) "
7478 		  "is modified by test or loop body.",
7479 		  sRefSet_unparsePlain (tuses)),
7480 		 test->loc);
7481 	    }
7482 	  else
7483 	    {
7484 	      if (sRefSet_isEmpty (tuncon))
7485 		{
7486 		  voptgenerror
7487 		    (FLG_INFLOOPSUNCON,
7488 		     message ("Suspected infinite loop.  No condition values "
7489 			      "modified.  Modification possible through "
7490 			      "unconstrained calls: %q",
7491 			      sRefSet_unparsePlain (suncon)),
7492 		     test->loc);
7493 		}
7494 	      else
7495 		{
7496 		  voptgenerror
7497 		    (FLG_INFLOOPSUNCON,
7498 		     message ("Suspected infinite loop.  No condition values "
7499 			      "modified.  Possible undetected dependency through "
7500 			      "unconstrained calls in loop test: %q",
7501 			      sRefSet_unparsePlain (tuncon)),
7502 		     test->loc);
7503 		}
7504 	    }
7505 	}
7506 
7507       sRefSet_free (sets);
7508     }
7509 }
7510 
exprNode_while(exprNode t,exprNode b)7511 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7512 {
7513   exprNode ret;
7514   bool emptyErr = FALSE;
7515 
7516   if (context_maybeSet (FLG_WHILEEMPTY))
7517     {
7518       if (exprNode_isEmptyStatement (b))
7519 	{
7520 	  emptyErr = optgenerror
7521 	    (FLG_WHILEEMPTY,
7522 	     cstring_makeLiteral
7523 	     ("Body of while statement is empty"),
7524 	     exprNode_loc (b));
7525 	}
7526     }
7527 
7528   if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7529     {
7530       if (exprNode_isDefined (b)
7531 	  && !exprNode_isBlock (b))
7532 	{
7533 	  if (context_inIterDef ()
7534 	      && (b->kind == XPR_STMTLIST
7535 		  || b->kind == XPR_TOK))
7536 	    {
7537 	      ; /* no error */
7538 	    }
7539 	  else
7540 	    {
7541 	      voptgenerror (FLG_WHILEBLOCK,
7542 			    message
7543 			    ("Body of while statement is not a block: %s",
7544 			     exprNode_unparse (b)),
7545 			    exprNode_loc (b));
7546 	    }
7547 	}
7548     }
7549 
7550   if (exprNode_isError (t))
7551     {
7552       if (exprNode_isError (b))
7553 	{
7554 	  ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7555 	}
7556       else
7557 	{
7558 	  ret = exprNode_createPartialCopy (b);
7559 	}
7560     }
7561   else
7562     {
7563       exprNode test;
7564 
7565       ret = exprNode_createPartialCopy (t);
7566 
7567       llassert (t->kind == XPR_WHILEPRED);
7568 
7569       test = exprData_getSingle (t->edata);
7570 
7571       if (!exprNode_isError (b) && exprNode_isDefined (test))
7572 	{
7573 	  if (context_maybeSet (FLG_INFLOOPS)
7574 	      || context_maybeSet (FLG_INFLOOPSUNCON))
7575 	    {
7576 	      /*
7577 	      ** check that some variable in the predicate is set by the body
7578               ** if the predicate uses any variables
7579               */
7580 
7581 	      checkInfiniteLoop (test, b);
7582 	    }
7583 
7584 	  exprNode_mergeUSs (ret, b);
7585 
7586 	  if (exprNode_isDefined (b))
7587 	    {
7588 	      ret->exitCode = exitkind_makeConditional (b->exitCode);
7589 	    }
7590 	}
7591     }
7592 
7593   ret->edata = exprData_makePair (t, b);
7594   ret->kind = XPR_WHILE;
7595 
7596   if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7597     {
7598       voptgenerror
7599 	(FLG_ALWAYSEXITS,
7600 	 message ("Predicate always exits: %s", exprNode_unparse (t)),
7601 	 exprNode_loc (t));
7602     }
7603 
7604   ret->exitCode = XK_NEVERESCAPE;
7605 
7606   /*
7607   ** If loop is infinite, and there is no break inside,
7608   ** exit code is never reach.
7609   */
7610 
7611   if (exprNode_knownIntValue (t))
7612     {
7613       if (!exprNode_isZero (t))
7614 	{
7615 	  if (exprNode_isDefined (b))
7616 	    {
7617 	      if (!b->canBreak)
7618 		{
7619 		  /* Really, it means never reached. */
7620 		  ret->exitCode = XK_MUSTEXIT;
7621 		}
7622 	    }
7623 	}
7624     }
7625   else
7626     {
7627       ;
7628     }
7629 
7630   ret->canBreak = FALSE;
7631   ret->mustBreak = FALSE;
7632 
7633   return ret;
7634 }
7635 
7636 /*
7637 ** do { b } while (t);
7638 **
7639 ** note: body passed as first argument
7640 */
7641 
exprNode_doWhile(exprNode b,exprNode t)7642 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7643 {
7644   exprNode ret;
7645 
7646   DPRINTF (("Do while: %s / %s",
7647 	    exprNode_unparse (b), exprNode_unparse (t)));
7648 
7649   if (exprNode_isError (t))
7650     {
7651       if (exprNode_isError (b))
7652 	{
7653 	  ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7654 	}
7655       else
7656 	{
7657 	  ret = exprNode_createPartialCopy (b);
7658 
7659 	  ret->exitCode = exitkind_makeConditional (b->exitCode);
7660 	  exprNode_checkUse (ret, b->sref, b->loc);
7661 	  ret->exitCode = b->exitCode;
7662 	  ret->canBreak = b->canBreak;
7663 	  ret->mustBreak = FALSE;
7664 	}
7665     }
7666   else
7667     {
7668       DPRINTF (("Do while: %s / %s",
7669 		exitkind_unparse (t->exitCode),
7670 		exitkind_unparse (b->exitCode)));
7671 
7672       ret = exprNode_createPartialCopy (t);
7673       exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7674 
7675       if (!exprNode_isError (b))
7676 	{
7677 	  /*
7678 	  ** forgot the copy's --- why wasn't this detected??
7679 	  */
7680 
7681 	  ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7682 	  ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7683 	  ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7684 
7685 	  /* left this out --- causes and aliasing bug (infinite loop)
7686 	     should be detected?? */
7687 
7688 	  exprNode_checkUse (ret, b->sref, b->loc);
7689 	  exprNode_mergeUSs (ret, t);
7690 	  exprNode_checkUse (ret, t->sref, t->loc);
7691 
7692 	  /* evans 2001-10-05: while loop can break */
7693 	  ret->exitCode = exitkind_makeConditional (b->exitCode);
7694 
7695 	  DPRINTF (("Do while: %s",
7696 		    exitkind_unparse (ret->exitCode)));
7697 
7698 	  ret->canBreak = b->canBreak;
7699 
7700 	  /* Always FALSE for doWhile loops - break's when test is false */
7701 	  ret->mustBreak = FALSE; /* b->mustBreak; */
7702 	}
7703     }
7704 
7705   context_exitDoWhileClause (t);
7706 
7707   ret->kind = XPR_DOWHILE;
7708   ret->edata = exprData_makePair (t, b);
7709   return ret;
7710 }
7711 
exprNode_loopMustExec(exprNode forPred)7712 bool exprNode_loopMustExec (exprNode forPred)
7713 {
7714   /*
7715   ** Returns true if it is obvious that the loop always executes at least once
7716   **
7717   ** For now, we only identify the most obvious cases.  Should be true anytime
7718   ** we can prove init => !test.
7719   */
7720 
7721   if (exprNode_isDefined (forPred))
7722     {
7723       exprNode init, test, inc;
7724       exprData edata;
7725 
7726       llassert (forPred->kind == XPR_FORPRED);
7727 
7728       edata = forPred->edata;
7729       init = exprData_getTripleInit (edata);
7730       test = exprData_getTripleTest (edata);
7731       inc = exprData_getTripleInc (edata);
7732 
7733       if (exprNode_isAssign (init))
7734 	{
7735 	  exprNode loopVar = exprData_getOpA (init->edata);
7736 	  exprNode loopInit = exprData_getOpB (init->edata);
7737 
7738 	  if (exprNode_isDefined (test) && test->kind == XPR_OP)
7739 	    {
7740 	      exprNode testVar = exprData_getOpA (test->edata);
7741 	      exprNode testVal = exprData_getOpB (test->edata);
7742 	      lltok comp = exprData_getOpTok (test->edata);
7743 	      int opid = lltok_getTok (comp);
7744 
7745 	      DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7746 			exprNode_unparse (testVar)));
7747 
7748 	      if (exprNode_sameStorage (loopVar, testVar))
7749 		{
7750 		  multiVal valinit = exprNode_getValue (loopInit);
7751 		  multiVal valtest = exprNode_getValue (testVal);
7752 
7753 		  DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7754 			    multiVal_unparse (valtest)));
7755 
7756 		  if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7757 		    {
7758 		      long v1 = multiVal_forceInt (valinit);
7759 		      long v2 = multiVal_forceInt (valtest);
7760 
7761 		      DPRINTF (("Here: %ld %ld", v1, v2));
7762 
7763 		      if ((opid == EQ_OP && v1 < v2)
7764 			  || (opid == NE_OP && v1 != v2)
7765 			  || (opid == TLT && v1 <= v2)
7766 			  || (opid == TGT && v1 >= v2)
7767 			  || (opid == LE_OP && v1 < v2)
7768 			  || (opid == GE_OP && v1 > v2))
7769 			{
7770 			  DPRINTF (("mustexec if inc"));
7771 			  return TRUE;
7772 			}
7773 		    }
7774 		}
7775 	    }
7776 	}
7777     }
7778 
7779   DPRINTF (("loop must exec: FALSE"));
7780   return FALSE;
7781 }
7782 
exprNode_for(exprNode inc,exprNode body)7783 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7784 {
7785   exprNode ret;
7786   bool emptyErr = FALSE;
7787 
7788   if (context_maybeSet (FLG_FOREMPTY))
7789     {
7790       if (exprNode_isEmptyStatement (body))
7791 	{
7792 	  emptyErr = optgenerror
7793 	    (FLG_FOREMPTY,
7794 	     cstring_makeLiteral
7795 	     ("Body of for statement is empty"),
7796 	     exprNode_loc (body));
7797 	}
7798     }
7799 
7800   if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7801     {
7802       if (exprNode_isDefined (body)
7803 	  && !exprNode_isBlock (body))
7804 	{
7805 	  if (context_inIterDef ()
7806 	      && (body->kind == XPR_STMTLIST
7807 		  || body->kind == XPR_TOK))
7808 	    {
7809 	      ; /* no error */
7810 	    }
7811 	  else
7812 	    {
7813 	      voptgenerror (FLG_FORBLOCK,
7814 			    message
7815 			    ("Body of for statement is not a block: %s",
7816 			     exprNode_unparse (body)),
7817 			    exprNode_loc (body));
7818 	    }
7819 	}
7820     }
7821 
7822   /*
7823   ** for ud purposes:  (alreadly) init -> test -> (now) LOOP: body + inc + test
7824   */
7825 
7826   if (exprNode_isError (body))
7827     {
7828       ret = exprNode_createPartialCopy (inc);
7829     }
7830   else
7831     {
7832       ret = exprNode_createPartialCopy (body);
7833 
7834       ret->exitCode = exitkind_makeConditional (body->exitCode);
7835 
7836       exprNode_mergeUSs (inc, body);
7837 
7838       if (exprNode_isDefined (inc))
7839 	{
7840 	  exprNode tmp;
7841 
7842 	  context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7843 
7844 	  tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7845 	  exprNode_freeShallow (tmp);
7846 
7847 	  context_clearMessageAnnote ();
7848 	  context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7849 
7850 	  tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7851 	  exprNode_freeShallow (tmp);
7852 
7853 	  context_clearMessageAnnote ();
7854 
7855 	  ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7856 	  ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7857 	  ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7858 	}
7859     }
7860 
7861   ret->kind = XPR_FOR;
7862   ret->edata = exprData_makePair (inc, body);
7863 
7864   if (exprNode_isDefined (inc)) {
7865     exprNode test = exprData_getTripleTest (inc->edata);
7866 
7867     if (exprNode_isUndefined (test)) {
7868       if (exprNode_isDefined (body)) {
7869 	if (!body->canBreak) {
7870 	  /* Really, it means never reached. */
7871 	  ret->exitCode = XK_MUSTEXIT;
7872 	}
7873       }
7874     }
7875   }
7876 
7877   return (ret);
7878 }
7879 
7880 /*
7881 ** for (init; test; inc)
7882 ** ==>
7883 ** init;
7884 ** while (test) { body; inc; }
7885 **
7886 ** Now: check use of init (may set vars for test)
7887 **      check use of test
7888 **      no checks on inc
7889 _*/
7890 
exprNode_getForGuards(exprNode pred)7891 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7892 {
7893   exprNode test;
7894 
7895   if (exprNode_isError (pred)) return guardSet_undefined;
7896 
7897   llassert (pred->kind == XPR_FORPRED);
7898 
7899   test = exprData_getTripleTest (pred->edata);
7900 
7901   if (!exprNode_isError (test))
7902     {
7903       return (test->guards);
7904     }
7905 
7906   return guardSet_undefined;
7907 }
7908 
exprNode_whilePred(exprNode test)7909 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7910 {
7911   exprNode ret = exprNode_createSemiCopy (test);
7912 
7913   if (exprNode_isDefined (test))
7914     {
7915       exprNode_copySets (ret, test);
7916       exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7917       exprNode_checkUse (ret, test->sref, test->loc);
7918 
7919       exprNode_produceGuards (test);
7920 
7921       ret->guards = guardSet_copy (test->guards);
7922     }
7923 
7924   ret->edata = exprData_makeSingle (test);
7925   ret->kind = XPR_WHILEPRED;
7926   return ret;
7927 }
7928 
exprNode_forPred(exprNode init,exprNode test,exprNode inc)7929 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7930 			   /*@only@*/ exprNode inc)
7931 {
7932   exprNode ret;
7933 
7934   /*
7935   ** for ud purposes:  init -> test -> LOOP: [ body, inc ]
7936   */
7937 
7938   exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7939 
7940   if (!exprNode_isError (inc))
7941     {
7942       ret = exprNode_createPartialCopy (inc);
7943     }
7944   else
7945     {
7946       if (!exprNode_isError (init))
7947 	{
7948 	  ret = exprNode_createPartialCopy (init);
7949 	}
7950       else if (!exprNode_isError (test))
7951 	{
7952 	  ret = exprNode_createPartialCopy (test);
7953 	}
7954       else
7955 	{
7956 	  ret = exprNode_createUnknown ();
7957 	}
7958     }
7959 
7960   exprNode_mergeUSs (ret, init);
7961 
7962   if (exprNode_isDefined (init))
7963     {
7964       exprNode_checkUse (ret, init->sref, init->loc);
7965     }
7966 
7967   exprNode_mergeUSs (ret, test);
7968 
7969   if (exprNode_isDefined (test))
7970     {
7971       exprNode_checkUse (ret, test->sref, test->loc);
7972     }
7973 
7974   ret->kind = XPR_FORPRED;
7975   ret->edata = exprData_makeFor (init, test, inc);
7976   return (ret);
7977 }
7978 
exprNode_goto(cstring label)7979 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7980 {
7981   exprNode ret = exprNode_createUnknown ();
7982 
7983   if (context_inMacro ())
7984     {
7985       voptgenerror (FLG_MACROSTMT,
7986 		    message ("Macro %s uses goto (not functional)",
7987 			     context_inFunctionName ()),
7988 		    g_currentloc);
7989     }
7990 
7991   ret->kind = XPR_GOTO;
7992   ret->edata = exprData_makeLiteral (label);
7993   ret->mustBreak = TRUE;
7994   ret->exitCode = XK_GOTO;
7995   ret->canBreak = TRUE;
7996   return ret;
7997 }
7998 
exprNode_continue(lltok l,int qcontinue)7999 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
8000 {
8001   exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
8002 
8003   ret->kind = XPR_CONTINUE;
8004   ret->edata = exprData_makeTok (l);
8005   ret->canBreak = TRUE;
8006   ret->mustBreak = TRUE;
8007 
8008   if (qcontinue == QSAFEBREAK)
8009     {
8010       ; /* no checking */
8011     }
8012   else if (qcontinue == QINNERCONTINUE)
8013     {
8014       if (!context_inDeepLoop ())
8015 	{
8016 	  voptgenerror
8017 	    (FLG_LOOPLOOPCONTINUE,
8018 	     cstring_makeLiteral ("Continue statement marked with innercontinue "
8019 				  "is not inside a nested loop"),
8020 	     exprNode_loc (ret));
8021 	}
8022     }
8023   else if (qcontinue == BADTOK)
8024     {
8025       if (context_inDeepLoop ())
8026 	{
8027 	  voptgenerror
8028 	    (FLG_LOOPLOOPCONTINUE,
8029 	     cstring_makeLiteral ("Continue statement in nested loop"),
8030 	     exprNode_loc (ret));
8031 	}
8032     }
8033   else
8034     {
8035       llbuglit ("exprNode_continue: bad qcontinue");
8036     }
8037 
8038   return ret;
8039 }
8040 
exprNode_break(lltok l,int bqual)8041 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
8042 {
8043   exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
8044   clause breakClause = context_breakClause ();
8045 
8046   ret->kind = XPR_BREAK;
8047   ret->edata = exprData_makeTok (l);
8048   ret->canBreak = TRUE;
8049   ret->mustBreak = TRUE;
8050 
8051   if (breakClause == NOCLAUSE)
8052     {
8053       voptgenerror
8054 	(FLG_SYNTAX,
8055 	 cstring_makeLiteral ("Break not inside while, for or switch statement"),
8056 	 exprNode_loc (ret));
8057     }
8058   else
8059     {
8060       if (bqual != BADTOK)
8061 	{
8062 	  switch (bqual)
8063 	    {
8064 	    case QSAFEBREAK:
8065 	      break;
8066 	    case QINNERBREAK:
8067 	      if (breakClause == SWITCHCLAUSE)
8068 		{
8069 		  if (!context_inDeepSwitch ())
8070 		    {
8071 		      voptgenerror (FLG_SYNTAX,
8072 				    cstring_makeLiteral
8073 				    ("Break preceded by innerbreak is not in a deep switch"),
8074 				    exprNode_loc (ret));
8075 		    }
8076 		}
8077 	      else
8078 		{
8079 		  if (!context_inDeepLoop ())
8080 		    {
8081 		      voptgenerror (FLG_SYNTAX,
8082 				    cstring_makeLiteral
8083 				    ("Break preceded by innerbreak is not in a deep loop"),
8084 				    exprNode_loc (ret));
8085 		    }
8086 		}
8087 	      break;
8088 	    case QLOOPBREAK:
8089 	      if (breakClause == SWITCHCLAUSE)
8090 		{
8091 		  voptgenerror (FLG_SYNTAX,
8092 				cstring_makeLiteral
8093 				("Break preceded by loopbreak is breaking a switch"),
8094 				exprNode_loc (ret));
8095 		}
8096 	      break;
8097 	    case QSWITCHBREAK:
8098 	      if (breakClause != SWITCHCLAUSE)
8099 		{
8100 		  voptgenerror
8101 		    (FLG_SYNTAX,
8102 		     message ("Break preceded by switchbreak is breaking %s",
8103 			      cstring_makeLiteralTemp
8104 			      ((breakClause == WHILECLAUSE
8105 				|| breakClause == DOWHILECLAUSE) ? "a while loop"
8106 			       : (breakClause == FORCLAUSE) ? "a for loop"
8107 			       : (breakClause == ITERCLAUSE) ? "an iterator"
8108 			       : "<error loop>")),
8109 		     exprNode_loc (ret));
8110 		}
8111 	      break;
8112 	    BADDEFAULT;
8113 	    }
8114 	}
8115       else
8116 	{
8117 	  if (breakClause == SWITCHCLAUSE)
8118 	    {
8119 	      clause nextBreakClause = context_nextBreakClause ();
8120 
8121 	      switch (nextBreakClause)
8122 		{
8123 		case NOCLAUSE: break;
8124 		case WHILECLAUSE:
8125 		case DOWHILECLAUSE:
8126 		case FORCLAUSE:
8127 		case ITERCLAUSE:
8128 		  voptgenerror
8129 		    (FLG_LOOPSWITCHBREAK,
8130 		     cstring_makeLiteral ("Break statement in switch inside loop"),
8131 		     exprNode_loc (ret));
8132 		  break;
8133 		case SWITCHCLAUSE:
8134 		  voptgenerror
8135 		    (FLG_SWITCHSWITCHBREAK,
8136 		     cstring_makeLiteral ("Break statement in switch inside switch"),
8137 		     exprNode_loc (ret));
8138 		  break;
8139 		BADDEFAULT;
8140 		}
8141 	    }
8142 	  else
8143 	    {
8144 	      if (context_inDeepLoop ())
8145 		{
8146 		  voptgenerror
8147 		    (FLG_LOOPLOOPBREAK,
8148 		     cstring_makeLiteral ("Break statement in nested loop"),
8149 		     exprNode_loc (ret));
8150 		}
8151 	      else
8152 		{
8153 		  if (context_inDeepLoopSwitch ())
8154 		    {
8155 		      voptgenerror
8156 			(FLG_SWITCHLOOPBREAK,
8157 			 cstring_makeLiteral ("Break statement in loop inside switch"),
8158 			 exprNode_loc (ret));
8159 		    }
8160 		}
8161 	    }
8162 	}
8163     }
8164 
8165   return ret;
8166 }
8167 
exprNode_nullReturn(lltok t)8168 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
8169 {
8170   fileloc loc = lltok_getLoc (t);
8171   exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
8172 
8173   context_returnFunction ();
8174   exprChecks_checkNullReturn (loc);
8175 
8176   ret->kind = XPR_NULLRETURN;
8177   ret->edata = exprData_makeTok (t);
8178   ret->exitCode = XK_MUSTRETURN;
8179   return ret;
8180 }
8181 
exprNode_return(exprNode e)8182 exprNode exprNode_return (/*@only@*/ exprNode e)
8183 {
8184   exprNode ret;
8185 
8186   if (exprNode_isError (e))
8187     {
8188       ret = exprNode_createUnknown ();
8189     }
8190   else
8191     {
8192       ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
8193 
8194       exprNode_checkUse (ret, e->sref, e->loc);
8195       exprNode_checkReturn (e);
8196     }
8197 
8198   context_returnFunction ();
8199   ret->kind = XPR_RETURN;
8200   ret->edata = exprData_makeSingle (e);
8201   ret->exitCode = XK_MUSTRETURN;
8202 
8203   return (ret);
8204 }
8205 
exprNode_comma(exprNode e1,exprNode e2)8206 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
8207 {
8208   exprNode ret;
8209 
8210   if (exprNode_isError (e1))
8211     {
8212       if (exprNode_isError (e2))
8213 	{
8214 	  ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8215 	}
8216       else
8217 	{
8218 	  ret = exprNode_createPartialCopy (e2);
8219 	  exprNode_checkUse (ret, e2->sref, e2->loc);
8220 	  ret->sref = e2->sref;
8221 	}
8222     }
8223   else
8224     {
8225       ret = exprNode_createPartialCopy (e1);
8226 
8227       exprNode_checkUse (ret, e1->sref, e1->loc);
8228 
8229       if (!exprNode_isError (e2))
8230 	{
8231 	  exprNode_mergeUSs (ret, e2);
8232 	  exprNode_checkUse (ret, e2->sref, e2->loc);
8233 	  ret->sref = e2->sref;
8234 	}
8235     }
8236 
8237   ret->kind = XPR_COMMA;
8238   ret->edata = exprData_makePair (e1, e2);
8239 
8240   if (exprNode_isDefined (e1))
8241     {
8242       if (exprNode_isDefined (e2))
8243 	{
8244 	  ret->typ = e2->typ;
8245 
8246 	  if (exprNode_mustEscape (e1) || e1->mustBreak)
8247 	    {
8248 	      voptgenerror
8249 		(FLG_UNREACHABLE,
8250 		 message ("Second clause of comma expression is unreachable: %s",
8251 			  exprNode_unparse (e2)),
8252 		 exprNode_loc (e2));
8253 	    }
8254 
8255 	  ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8256 	  ret->mustBreak = e1->mustBreak || e2->mustBreak;
8257 	  ret->canBreak = e1->canBreak || e2->canBreak;
8258 	}
8259       else
8260 	{
8261 	  if (exprNode_mustEscape (e1) || e1->mustBreak)
8262 	    {
8263 	      voptgenerror
8264 		(FLG_UNREACHABLE,
8265 		 message ("Second clause of comma expression is unreachable: %s",
8266 			  exprNode_unparse (e2)),
8267 		 exprNode_loc (e2));
8268 	    }
8269 
8270 	  ret->exitCode = e1->exitCode;
8271 	  ret->canBreak = e1->canBreak;
8272 	}
8273     }
8274   else
8275     {
8276       if (exprNode_isDefined (e2))
8277 	{
8278 	  ret->exitCode = e2->exitCode;
8279 	  ret->mustBreak = e2->mustBreak;
8280 	  ret->canBreak = e2->canBreak;
8281 	}
8282     }
8283 
8284   return (ret);
8285 }
8286 
exprNode_checkOneInit(exprNode el,exprNode val)8287 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8288 {
8289   ctype t1 = exprNode_getType (el);
8290   ctype t2 = exprNode_getType (val);
8291   bool hasError = FALSE;
8292 
8293   DPRINTF (("Check one init: %s / %s",
8294 	    exprNode_unparse (el),
8295 	    exprNode_unparse (val)));
8296 
8297   if (ctype_isUnknown (t1))
8298     {
8299       voptgenerror (FLG_IMPTYPE,
8300 		    message ("Variable has unknown (implicitly int) type: %s",
8301 			     exprNode_unparse (el)),
8302 		    el->loc);
8303 
8304       t1 = ctype_int;
8305       el->typ = ctype_int;
8306     }
8307 
8308   if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8309     {
8310       exprNodeList vals = exprData_getArgs (val->edata);
8311 
8312       DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8313       DPRINTF (("Type: %s", ctype_unparse (t1)));
8314 
8315       if (ctype_isRealAP (t1))
8316 	{
8317 	  int i = 0;
8318 	  int nerrors = 0;
8319 
8320 	  if (ctype_isFixedArray (t1))
8321 	    {
8322 	      size_t nelements = ctype_getArraySize (t1);
8323 
8324 	      DPRINTF (("Checked array: %s / %d",
8325 			ctype_unparse (t1), nelements));
8326 
8327 	      if (exprNode_isStringLiteral (val))
8328 		{
8329 		  exprNode_checkStringLiteralLength (t1, val);
8330 		}
8331 	      else
8332 		{
8333 		  if (exprNodeList_size (vals) != size_toInt (nelements))
8334 		    {
8335 		      hasError = optgenerror
8336 			(exprNodeList_size (vals) > size_toInt (nelements)
8337 			 ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8338 			 message ("Initializer block for "
8339 				  "%s has %d element%&, but declared as %s: %q",
8340 				  exprNode_unparse (el),
8341 				  exprNodeList_size (vals),
8342 				  ctype_unparse (t1),
8343 				  exprNodeList_unparse (vals)),
8344 			 val->loc);
8345 		    }
8346 		}
8347 	    }
8348 
8349 	  exprNodeList_elements (vals, oneval)
8350 	    {
8351 	      cstring istring = message ("%d", i);
8352 	      exprNode newel =
8353 		exprNode_arrayFetch
8354 		  (exprNode_fakeCopy (el),
8355 		   exprNode_numLiteral (ctype_int, istring,
8356 					fileloc_copy (el->loc), i));
8357 
8358 	      if (exprNode_isDefined (newel))
8359 		{
8360 		  if (exprNodeList_size (vals) == 1
8361 		      && ctype_isString (exprNode_getType (oneval))
8362 		      && ctype_isChar (exprNode_getType (newel)))
8363 		    {
8364 		      exprNode_freeIniter (newel);
8365 		    }
8366 		  else
8367 		    {
8368 		      if (exprNode_checkOneInit (newel, oneval))
8369 			{
8370 			  hasError = TRUE;
8371 			  nerrors++;
8372 
8373 			  if (nerrors > 3 && exprNodeList_size (vals) > 6)
8374 			    {
8375 			      llgenmsg
8376 				(message ("Additional initialization errors "
8377 					  "for %s not reported",
8378 					  exprNode_unparse (el)),
8379 				 exprNode_loc (el));
8380 			      exprNode_freeIniter (newel);
8381 			      break;
8382 			    }
8383 			  else
8384 			    {
8385 			      exprNode_freeIniter (newel);
8386 			    }
8387 			}
8388 		      else
8389 			{
8390 			  exprNode_freeIniter (newel);
8391 			}
8392 		    }
8393 		}
8394 
8395 	      cstring_free (istring);
8396 	      i++;
8397 	      /*@-branchstate@*/
8398 	    } end_exprNodeList_elements;
8399 	  /*@=branchstate@*/
8400 	}
8401       else if (ctype_isStruct (ctype_realType (t1)))
8402 	{
8403 	  uentryList fields = ctype_getFields (t1);
8404 	  int i = 0;
8405 
8406 	  if (uentryList_size (fields) != exprNodeList_size (vals))
8407 	    {
8408 	      if (uentryList_size (fields) > exprNodeList_size (vals))
8409 		{
8410 		  hasError = optgenerror
8411 		    (FLG_FULLINITBLOCK,
8412 		     message ("Initializer block for "
8413 			      "%s has %d field%&, but %s has %d field%&: %q",
8414 			      exprNode_unparse (el),
8415 			      exprNodeList_size (vals),
8416 			      ctype_unparse (t1),
8417 			      uentryList_size (fields),
8418 			      exprNodeList_unparse (vals)),
8419 		     val->loc);
8420 		}
8421 	      else
8422 		{
8423 		  hasError = optgenerror
8424 		    (FLG_TYPE,
8425 		     message ("Initializer block for "
8426 			      "%s has %d field%&, but %s has %d field%&: %q",
8427 			      exprNode_unparse (el),
8428 			      exprNodeList_size (vals),
8429 			      ctype_unparse (t1),
8430 			      uentryList_size (fields),
8431 			      exprNodeList_unparse (vals)),
8432 		     val->loc);
8433 		}
8434 	    }
8435 	  else
8436 	    {
8437 	      exprNodeList_elements (vals, oneval)
8438 		{
8439 		  uentry thisfield = uentryList_getN (fields, i);
8440 		  exprNode newel =
8441 		    exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8442 					     exprNode_loc (el),
8443 					     uentry_getName (thisfield));
8444 
8445 		  if (exprNode_isDefined (newel))
8446 		    {
8447 		      if (exprNode_checkOneInit (newel, oneval))
8448 			{
8449 			  hasError = TRUE;
8450 			}
8451 
8452 		      exprNode_freeIniter (newel);
8453 		    }
8454 
8455 		  i++;
8456 		} end_exprNodeList_elements;
8457 	    }
8458 	}
8459       /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8460       else if (ctype_isUnion (ctype_realType (t1)))
8461 	{
8462 	  uentryList fields = ctype_getFields (t1);
8463 	  int i = 0;
8464 
8465 	  /*
8466 	  ** Union initializers set the first member always.
8467 	  */
8468 
8469 	  DPRINTF (("Union initializer: %s / %s",
8470 		    exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8471 
8472 	  if (exprNodeList_size (vals) != 1)
8473 	    {
8474 	      hasError = optgenerror
8475 		(FLG_TYPE,
8476 		 message ("Initializer block for union "
8477 			  "%s has %d elements, union initializers should have one element: %q",
8478 			  exprNode_unparse (el),
8479 			  exprNodeList_size (vals),
8480 			  exprNodeList_unparse (vals)),
8481 		 val->loc);
8482 	    }
8483 	  else
8484 	    {
8485 	      exprNode oneval = exprNodeList_head (vals);
8486 	      uentry thisfield = uentryList_getN (fields, i);
8487 	      exprNode newel =
8488 		exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8489 					 exprNode_loc (el),
8490 					 uentry_getName (thisfield));
8491 
8492 	      if (exprNode_isDefined (newel))
8493 		{
8494 		  if (exprNode_checkOneInit (newel, oneval))
8495 		    {
8496 		      hasError = TRUE;
8497 		    }
8498 
8499 		  exprNode_freeIniter (newel);
8500 		}
8501 	    }
8502 	}
8503       else
8504 	{
8505 	  hasError = optgenerror
8506 	    (FLG_TYPE,
8507 	     message ("Initializer block used for "
8508 		      "%s where %t is expected: %s",
8509 		      exprNode_unparse (el), t1, exprNode_unparse (val)),
8510 	     val->loc);
8511 	}
8512     }
8513   else
8514     {
8515       if (exprNode_isDefined (val))
8516 	{
8517 	  doAssign (el, val, TRUE);
8518 
8519 	  if (!exprNode_matchType (t1, val))
8520 	    {
8521 	      hasError = gentypeerror
8522 		(t1, val, t2, el,
8523 		 message ("Initial value of %s is type %t, "
8524 			  "expects %t: %s",
8525 			  exprNode_unparse (el),
8526 			  t2, t1, exprNode_unparse (val)),
8527 		 val->loc);
8528 	    }
8529 	}
8530     }
8531 
8532   return hasError;
8533 }
8534 
8535 static /*@notnull@*/ exprNode
exprNode_makeInitializationAux(idDecl t)8536 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8537 {
8538   exprNode ret;
8539 
8540   DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8541 
8542   if (usymtab_exists (idDecl_observeId (t)))
8543     {
8544       uentry ue = usymtab_lookup (idDecl_observeId (t));
8545       ret = exprNode_createId (ue);
8546     }
8547   else
8548     {
8549       uentry ue;
8550 
8551       DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8552 
8553       ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8554       ret = exprNode_fromIdentifierAux (ue);
8555 
8556       /*
8557       ** No error - this happens in old style declarations:
8558 
8559       voptgenerror
8560 	(FLG_UNRECOG,
8561 	 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8562 	 g_currentloc);
8563 
8564       **
8565       */
8566     }
8567 
8568   exprData_free (ret->edata, ret->kind);
8569   ret->edata = exprData_undefined;
8570   ret->exitCode = XK_NEVERESCAPE;
8571   ret->mustBreak = FALSE;
8572   ret->kind = XPR_INIT;
8573   return ret;
8574 }
8575 
exprNode_makeEmptyInitialization(idDecl t)8576 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8577 {
8578   exprNode ret = exprNode_makeInitializationAux (t);
8579   llassert (ret->edata == exprData_undefined);
8580   ret->edata = exprData_makeInit (t, exprNode_undefined);
8581   return ret;
8582 }
8583 
exprNode_makeInitialization(idDecl t,exprNode e)8584 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8585 				      /*@only@*/ exprNode e)
8586 {
8587   uentry ue = usymtab_lookup (idDecl_observeId (t));
8588   exprNode ret = exprNode_makeInitializationAux (t);
8589   fileloc loc = exprNode_loc (e);
8590 
8591   DPRINTF (("initialization: %s = %s", idDecl_unparse (t), exprNode_unparse (e)));
8592 
8593   if (exprNode_isError (e))
8594     {
8595       e = exprNode_createUnknown ();
8596       /* error: assume initializer is defined */
8597       sRef_setDefined (ret->sref, g_currentloc);
8598       ret->edata = exprData_makeInit (t, e);
8599     }
8600   else
8601     {
8602       ctype ct = ctype_realishType (ret->typ);
8603 
8604       /*
8605       ** evs - 9 Apr 1995
8606       **
8607       ** was addSafeUse --- what's the problem?
8608       **
8609       **   int x = 3, y = x ?
8610       */
8611 
8612       exprData_free (ret->edata, ret->kind);
8613       ret->edata = exprData_makeInit (t, e);
8614       DPRINTF (("ret: %s", exprNode_unparse (ret)));
8615 
8616       exprNode_checkUse (ret, e->sref, e->loc);
8617 
8618       if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8619 	{
8620 	  exprNode lhs = exprNode_createId (ue);
8621 
8622 	  /*
8623 	  ** static storage should be undefined before initializing
8624 	  */
8625 
8626 	  if (uentry_isStatic (ue))
8627 	    {
8628 	      sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8629 	    }
8630 
8631 	  (void) exprNode_checkOneInit (lhs, e);
8632 
8633 	  if (uentry_isStatic (ue))
8634 	    {
8635 	      sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8636 	    }
8637 
8638 	  exprNode_free (lhs);
8639 	}
8640       else
8641 	{
8642 	  if (!exprNode_matchType (ct, e))
8643 	    {
8644 	      if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8645 		{
8646 		  ;
8647 		}
8648 	      else
8649 		{
8650 		  (void) gentypeerror
8651 		    (exprNode_getType (e), e, exprNode_getType (ret), ret,
8652 		     message
8653 		     ("Variable %q initialized to type %t, expects %t: %s",
8654 		      uentry_getName (ue), exprNode_getType (e),
8655 		      exprNode_getType (ret),
8656 		      exprNode_unparse (e)),
8657 		     e->loc);
8658 		}
8659 	    }
8660 	}
8661 
8662       if (uentry_isStatic (ue))
8663 	{
8664 	  sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8665 	}
8666 
8667       if (exprNode_isStringLiteral (e)
8668 	  && (ctype_isArray (ct))
8669 	  && (ctype_isChar (ctype_realType (ctype_baseArrayPtr (ct)))))
8670 	{
8671 	  /*
8672 	  ** If t is a char [], the literal is copied.
8673 	  */
8674 
8675 	  exprNode_checkStringLiteralLength (ct, e);
8676 	  sRef_setDefState (ret->sref, SS_DEFINED, e->loc);
8677 	  ret->val = multiVal_copy (e->val);
8678 
8679 	  sRef_setNullTerminatedState (ret->sref);
8680 
8681 	  if (multiVal_isDefined (e->val))
8682 	    {
8683 	      cstring slit = multiVal_forceString (e->val);
8684 	      sRef_setLen (ret->sref, size_toInt (cstring_length (slit) + 1));
8685 	    }
8686 
8687 	  if (ctype_isFixedArray (ct))
8688 	    {
8689 	      sRef_setSize (ret->sref, size_toInt (ctype_getArraySize (ct)));
8690 	    }
8691 	}
8692       else
8693 	{
8694 	  doAssign (ret, e, TRUE);
8695 	}
8696 
8697       if (uentry_isStatic (ue))
8698 	{
8699 	  sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8700 	}
8701     }
8702 
8703   if (context_inIterDef ())
8704     {
8705       /* should check if it is yield */
8706       uentry_setUsed (ue, loc);
8707     }
8708   else
8709     {
8710       ;
8711     }
8712 
8713   exprNode_mergeUSs (ret, e);
8714   DPRINTF (("Ret: %s %p %p",
8715 	    exprNode_unparse (ret),
8716 	    ret->requiresConstraints,
8717 	    ret->ensuresConstraints));
8718 
8719   DPRINTF (("Ret: %s %s %s",
8720 	    exprNode_unparse (ret),
8721 	    constraintList_unparse (ret->requiresConstraints),
8722 	    constraintList_unparse (ret->ensuresConstraints)));
8723   return ret;
8724 }
8725 
exprNode_iter(uentry name,exprNodeList alist,exprNode body,uentry end)8726 exprNode exprNode_iter (/*@observer@*/ uentry name,
8727 			/*@only@*/ exprNodeList alist,
8728 			/*@only@*/ exprNode body,
8729 			/*@observer@*/ uentry end)
8730 {
8731   exprNode ret;
8732   cstring iname;
8733 
8734   llassert (uentry_isValid (name));
8735 
8736   uentry_setUsed (name, exprNode_loc (body));
8737 
8738   ret = exprNode_createPartialCopy (body);
8739   iname = uentry_getName (name);
8740 
8741   if (uentry_isInvalid (end))
8742     {
8743       llerror (FLG_ITERBALANCE,
8744 	       message ("Iter %s not balanced with end_%s", iname, iname));
8745     }
8746   else
8747     {
8748       cstring ename = uentry_getName (end);
8749 
8750       if (!cstring_equalPrefixLit (ename, "end_"))
8751 	{
8752 	  llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s",
8753 				      iname, iname, ename));
8754 	}
8755       else
8756 	{
8757 	  if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8758 	    {
8759 	      llerror (FLG_ITERBALANCE,
8760 		       message ("Iter %s not balanced with end_%s: %s",
8761 				iname, iname, ename));
8762 	    }
8763 	}
8764 
8765       cstring_free (ename);
8766     }
8767 
8768   context_exitIterClause (body);
8769 
8770   ret->kind = XPR_ITER;
8771   ret->edata = exprData_makeIter (name, alist, body, end);
8772 
8773   if (uentry_isIter (name))
8774     {
8775       (void) checkArgsReal (name, body,
8776 			    uentry_getParams (name), alist, TRUE, ret);
8777     }
8778 
8779   cstring_free (iname);
8780 
8781   return ret;
8782 }
8783 
8784 exprNode
exprNode_iterNewId(cstring s)8785 exprNode_iterNewId (/*@only@*/ cstring s)
8786 {
8787   exprNode e = exprNode_new ();
8788   uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8789 
8790   llassert (processingIterVars ());
8791 
8792   e->loc = context_getSaveLocation ();
8793 
8794   if (fileloc_isUndefined (e->loc))
8795     {
8796       fileloc_free (e->loc);
8797       e->loc = fileloc_copy (g_currentloc);
8798     }
8799 
8800   e->uses = sRefSet_new ();
8801   e->sets = sRefSet_new ();
8802   e->msets = sRefSet_new ();
8803   e->kind = XPR_VAR;
8804   e->val = multiVal_unknown ();
8805   e->guards = guardSet_new ();
8806   e->sref = sRef_undefined;
8807   e->isJumpPoint = FALSE;
8808   e->exitCode = XK_NEVERESCAPE;
8809 
8810   /*> missing fields, detected by splint <*/
8811   e->canBreak = FALSE;
8812   e->mustBreak = FALSE;
8813   e->etext = cstring_undefined;
8814 
8815   if (uentry_isYield (ue))
8816     {
8817       uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8818 					fileloc_copy (e->loc),
8819 					FALSE);
8820       sRef sr;
8821 
8822       uue = usymtab_supEntrySrefReturn (uue);
8823 
8824       sr = uentry_getSref (uue);
8825       sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8826       sr = uentry_getSref (uue);
8827       sRef_setDefined (sr, e->loc);
8828 
8829       e->typ = uentry_getType (uue);
8830       e->sref = sr;
8831       e->edata = exprData_makeId (uue);
8832       uentry_setUsed (uue, g_currentloc);
8833     }
8834   else
8835     {
8836       uentry uue;
8837 
8838       sRef_setGlobalScope ();
8839       uue = uentry_makeVariableLoc (s, ctype_unknown);
8840 
8841       e->typ = ctype_unknown;
8842       e->edata = exprData_makeId (uue);
8843 
8844       uentry_setUsed (uue, e->loc);
8845       uentry_setHasNameError (uue);
8846 
8847       if (context_getFlag (FLG_REPEATUNRECOG))
8848 	{
8849 	  uentry_markOwned (uue);
8850 	}
8851       else
8852 	{
8853 	  usymtab_supGlobalEntry (uue);
8854 	}
8855 
8856       sRef_clearGlobalScope ();
8857 
8858       voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8859 		    e->loc);
8860     }
8861 
8862 
8863   cstring_free (s);
8864 
8865   exprNode_defineConstraints(e);
8866   return (e);
8867 }
8868 
8869 exprNode
exprNode_iterExpr(exprNode e)8870 exprNode_iterExpr (/*@returned@*/ exprNode e)
8871 {
8872   if (!processingIterVars ())
8873     {
8874       llcontbuglit ("checkIterParam: not in iter");
8875       return e;
8876     }
8877 
8878   if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8879 				       iterParamNo ())))
8880     {
8881       if (exprNode_isDefined (e))
8882 	{
8883 	  if (fileloc_isDefined (e->loc))
8884 	    {
8885 	      voptgenerror
8886 		(FLG_ITERYIELD,
8887 		 message ("Yield parameter is not simple identifier: %s",
8888 			  exprNode_unparse (e)),
8889 		 e->loc);
8890 	    }
8891 	  else
8892 	    {
8893 	      voptgenerror
8894 		(FLG_ITERYIELD,
8895 		 message ("Yield parameter is not simple identifier: %s",
8896 			  exprNode_unparse (e)),
8897 		 g_currentloc);
8898 
8899 	    }
8900 	}
8901     }
8902   return e;
8903 }
8904 
8905 exprNode
exprNode_iterId(uentry c)8906 exprNode_iterId (/*@observer@*/ uentry c)
8907 {
8908   uentry ue;
8909 
8910   llassert (processingIterVars ());
8911 
8912   ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8913 			iterParamNo ());
8914 
8915   if (uentry_isYield (ue))
8916     {
8917       ctype ct = uentry_getType (ue);
8918       exprNode e = exprNode_createPlain (ct);
8919       cstring name = uentry_getName (c);
8920       uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8921 
8922       uentry_setUsed (ue, g_currentloc);
8923       uentry_setHasNameError (ue);
8924 
8925       cstring_free (name);
8926 
8927       e->kind = XPR_VAR;
8928       e->edata = exprData_makeId (le);
8929       e->loc = context_getSaveLocation ();
8930       e->sref = uentry_getSref (le);
8931 
8932       usymtab_supEntrySref (le);
8933 
8934       if (!context_inHeader ())
8935 	{
8936 	  if (optgenerror
8937 	      (FLG_ITERYIELD,
8938 	       message ("Yield parameter shadows local declaration: %q",
8939 			uentry_getName (c)),
8940 	       fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8941 	    {
8942 	      uentry_showWhereDeclared (c);
8943 	    }
8944 	}
8945 
8946       return e;
8947     }
8948 
8949   return (exprNode_fromIdentifierAux (c));
8950 }
8951 
exprNode_iterStart(uentry name,exprNodeList alist)8952 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8953 {
8954   exprNode ret = exprNode_create (ctype_unknown);
8955 
8956   ret->kind = XPR_ITERCALL;
8957   ret->edata = exprData_makeIterCall (name, alist);
8958 
8959   if (uentry_isIter (name))
8960     {
8961       uentryList params = uentry_getParams (name);
8962 
8963       if (context_inIterDef ()
8964 	  && uentryList_size (params) == exprNodeList_size (alist))
8965 	{
8966 	  int i = 0;
8967 
8968 	  exprNodeList_elements (alist, arg)
8969 	    {
8970 	      uentry parg = uentryList_getN (params, i);
8971 
8972 	      if (uentry_isYield (parg))
8973 		{
8974 		  uentry ue = exprNode_getUentry (arg);
8975 
8976 		  if (uentry_isValid (ue))
8977 		    {
8978 		      ;
8979 		    }
8980 		}
8981 
8982 	      i++;
8983 	    } end_exprNodeList_elements;
8984 	}
8985 
8986       (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8987       checkUnspecCall (ret, params, alist);
8988     }
8989 
8990   return ret;
8991 }
8992 
exprNode_getSref(exprNode e)8993 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8994 {
8995   if (exprNode_isDefined (e))
8996     {
8997       if (sRef_isInvalid (e->sref))
8998 	{
8999 	  /*@-mods@*/
9000 	  e->sref = sRef_makeUnknown ();
9001           sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
9002 	  /*@=mods@*/
9003 	  return e->sref;
9004 	}
9005       else
9006 	{
9007 	  return e->sref;
9008 	}
9009     }
9010   else
9011     {
9012       return sRef_undefined;
9013     }
9014 }
9015 
9016 /*@observer@*/ cstring
exprNode_unparseFirst(exprNode e)9017 exprNode_unparseFirst (exprNode e)
9018 {
9019   if (exprNode_isDefined (e))
9020     {
9021       cstring ret;
9022 
9023       if (e->kind == XPR_STMTLIST
9024 	  || e->kind == XPR_COMMA || e->kind == XPR_COND)
9025 	{
9026 	  exprNode first = exprData_getPairA (e->edata);
9027 
9028 	  if (exprNode_isDefined (first))
9029 	    {
9030 	      return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
9031 	    }
9032 	  else
9033 	    {
9034 	      return (cstring_makeLiteralTemp ("..."));
9035 	    }
9036 	}
9037 
9038       ret = cstring_elide (exprNode_unparse (e), 20);
9039       cstring_markOwned (ret);
9040 
9041       return (ret);
9042     }
9043   else
9044     {
9045       return cstring_makeLiteralTemp ("<error>");
9046     }
9047 }
9048 
9049 /*@observer@*/ cstring
exprNode_unparse(exprNode e)9050 exprNode_unparse (/*@temp@*/ exprNode e)
9051 {
9052   if (exprNode_isError (e))
9053     {
9054       return cstring_makeLiteralTemp ("<error>");
9055     }
9056 
9057   if (cstring_isDefined (e->etext))
9058     {
9059       return e->etext;
9060     }
9061   else
9062     {
9063       cstring ret = exprNode_doUnparse (e);
9064 
9065       /*@-modifies@*/ /* benevolent */
9066       e->etext = ret;
9067       /*@=modifies@*/
9068       return ret;
9069     }
9070 }
9071 
9072 /*@observer@*/ fileloc
exprNode_loc(exprNode e)9073 exprNode_loc (exprNode e)
9074 {
9075   if (exprNode_isError (e))
9076     {
9077       return (g_currentloc);
9078     }
9079   else
9080     {
9081       return (e->loc);
9082     }
9083 }
9084 
9085 /*
9086 ** executes exprNode e
9087 **    recursively rexecutes as though in original parse using
9088 **    information in e->edata
9089 */
9090 
exprNodeList_effect(exprNodeList e)9091 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
9092 {
9093   exprNodeList ret = exprNodeList_new ();
9094 
9095   exprNodeList_elements (e, current)
9096     {
9097       exprNodeList_addh (ret, exprNode_effect (current));
9098     } end_exprNodeList_elements;
9099 
9100   return ret;
9101 }
9102 
exprNode_effect(exprNode e)9103 static /*@only@*/ exprNode exprNode_effect (exprNode e)
9104    /*@globals internalState@*/
9105 {
9106   bool innerEffect = inEffect;
9107   exprNode ret;
9108   exprData data;
9109 
9110   inEffect = TRUE;
9111 
9112   context_clearJustPopped ();
9113 
9114   if (exprNode_isError (e))
9115     {
9116       ret = exprNode_undefined;
9117     }
9118   else
9119     {
9120       /*
9121       ** Turn off expose and dependent transfer checking.
9122       ** Need to pass exposed internal nodes,
9123       ** [ copying would be a waste! ]
9124       ** [ Actually, I think I wasted a lot more time than its worth ]
9125       ** [ trying to do this. ]
9126       */
9127 
9128       /*@-exposetrans@*/
9129       /*@-observertrans@*/
9130       /*@-dependenttrans@*/
9131 
9132       data = e->edata;
9133 
9134       switch (e->kind)
9135 	{
9136 	case XPR_PARENS:
9137 	  ret = exprNode_addParens (exprData_getUopTok (data),
9138 				    exprNode_effect (exprData_getUopNode (data)));
9139 	  break;
9140 	case XPR_ASSIGN:
9141 	  ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
9142 				 exprNode_effect (exprData_getOpB (data)),
9143 				 exprData_getOpTok (data));
9144 	  break;
9145 	case XPR_INITBLOCK:
9146 	  ret = exprNode_undefined;
9147 	  break;
9148 	case XPR_CALL:
9149 	  ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
9150 				       exprNodeList_effect (exprData_getArgs (data)));
9151 	  break;
9152 	case XPR_EMPTY:
9153 	  ret = e;
9154 	  break;
9155 
9156 	case XPR_LABEL:
9157 	  ret = e;
9158 	  break;
9159 
9160 	case XPR_CONST:
9161 	case XPR_VAR:
9162 	  {
9163 	    cstring id = exprData_getId (data);
9164 	    uentry ue = usymtab_lookupSafe (id);
9165 
9166 	    ret = exprNode_fromIdentifierAux (ue);
9167 	    ret->loc = fileloc_update (ret->loc, e->loc);
9168 	    break;
9169 	  }
9170 	case XPR_BODY:
9171 	  ret = e;
9172 	  break;
9173 	case XPR_FETCH:
9174 	  ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
9175 				     exprNode_effect (exprData_getPairB (data)));
9176 	  break;
9177 	case XPR_OP:
9178 	  /*
9179 	  ** evans 2002-03-15: for && and ||, need to do the guards also
9180 	  **                   this is what cgrammar.y does - should be
9181 	  **                   able to avoid duplication, but need to
9182 	  **                   time with grammar productions.
9183 	  */
9184 
9185 	  DPRINTF (("Effect: %s", exprNode_unparse (e)));
9186 
9187 	  if (lltok_getTok (exprData_getOpTok (data)) == AND_OP)
9188 	    {
9189 	      exprNode e1 = exprNode_effect (exprData_getOpA (data));
9190 	      exprNode e2;
9191 	      exprNode_produceGuards (e1);
9192 	      context_enterAndClause (e1);
9193 	      e2 = exprNode_effect (exprData_getOpB (data));
9194 
9195 	      ret = exprNode_op (e1, e2,
9196 				 exprData_getOpTok (data));
9197 
9198 	      context_exitAndClause (ret, e2);
9199 	    }
9200 	  else if (lltok_getTok (exprData_getOpTok (data)) == OR_OP)
9201 	    {
9202 	      exprNode e1 = exprNode_effect (exprData_getOpA (data));
9203 	      exprNode e2;
9204 	      exprNode_produceGuards (e1);
9205 	      context_enterOrClause (e1);
9206 	      e2 = exprNode_effect (exprData_getOpB (data));
9207 
9208 	      ret = exprNode_op (e1, e2,
9209 				 exprData_getOpTok (data));
9210 
9211 	      context_exitOrClause (ret, e2);
9212 	    }
9213 	  else
9214 	    {
9215 	      ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
9216 				 exprNode_effect (exprData_getOpB (data)),
9217 				 exprData_getOpTok (data));
9218 	    }
9219 	  break;
9220 
9221 	case XPR_POSTOP:
9222 	  ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
9223 				 exprData_getUopTok (data));
9224 	  break;
9225 	case XPR_PREOP:
9226 	  ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
9227 				exprData_getUopTok (data));
9228 	  break;
9229 
9230 	case XPR_OFFSETOF:
9231 	case XPR_SIZEOFT:
9232 	case XPR_SIZEOF:
9233 	case XPR_ALIGNOFT:
9234 	case XPR_ALIGNOF:
9235 	  ret = e;
9236 	  break;
9237 
9238 	case XPR_VAARG:
9239 	  ret = exprNode_vaArg (exprData_getCastTok (data),
9240 				exprNode_effect (exprData_getCastNode (data)),
9241 				exprData_getCastType (data));
9242 	  break;
9243 
9244 	case XPR_CAST:
9245 	  ret = exprNode_cast (exprData_getCastTok (data),
9246 			       exprNode_effect (exprData_getCastNode (data)),
9247 			       exprData_getCastType (data));
9248 	  break;
9249 	case XPR_ITERCALL:
9250 	  ret = exprNode_iterStart (exprData_getIterCallIter (data),
9251 				    exprNodeList_effect
9252 				    (exprData_getIterCallArgs (data)));
9253 	  break;
9254 
9255 	case XPR_ITER:
9256 	  ret = exprNode_iter (exprData_getIterSname (data),
9257 			       exprNodeList_effect (exprData_getIterAlist (data)),
9258 			       exprNode_effect (exprData_getIterBody (data)),
9259 			       exprData_getIterEname (data));
9260 	  break;
9261 
9262 	case XPR_FOR:
9263 	  ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
9264 			      exprNode_effect (exprData_getPairB (data)));
9265 	  break;
9266 
9267 	case XPR_FORPRED:
9268 	  ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9269 				  exprNode_effect (exprData_getTripleTest (data)),
9270 				  exprNode_effect (exprData_getTripleInc (data)));
9271 	  break;
9272 
9273 	case XPR_TOK:
9274 	  ret = exprNode_createTok (exprData_getTok (data));
9275 	  break;
9276 
9277 	case XPR_GOTO:
9278 	  ret = exprNode_goto (exprData_getLiteral (data));
9279 	  ret->loc = fileloc_update (ret->loc, e->loc);
9280 	  break;
9281 
9282 	case XPR_CONTINUE:
9283 	  ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9284 	  break;
9285 
9286 	case XPR_BREAK:
9287 	  ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9288 	  break;
9289 
9290 	case XPR_RETURN:
9291 	  ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9292 	  break;
9293 
9294 	case XPR_NULLRETURN:
9295 	  ret = exprNode_nullReturn (exprData_getTok (data));
9296 	  break;
9297 
9298 	case XPR_COMMA:
9299 	  ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9300 				exprNode_effect (exprData_getPairB (data)));
9301 	  break;
9302 
9303 	case XPR_COND:
9304 	  ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9305 			       exprNode_effect (exprData_getTripleTrue (data)),
9306 			       exprNode_effect (exprData_getTripleFalse (data)));
9307 	  break;
9308 	case XPR_IF:
9309 	  ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9310 			     exprNode_effect (exprData_getPairB (data)));
9311 	  break;
9312 
9313 	case XPR_IFELSE:
9314 	  ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9315 				 exprNode_effect (exprData_getTripleTrue (data)),
9316 				 exprNode_effect (exprData_getTripleFalse (data)));
9317 	  break;
9318 	case XPR_WHILEPRED:
9319 	  ret = exprNode_whilePred (exprData_getSingle (data));
9320 	  break;
9321 
9322 	case XPR_WHILE:
9323 	  ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9324 				exprNode_effect (exprData_getPairB (data)));
9325 	  break;
9326 
9327 	case XPR_DOWHILE:
9328 	  ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9329 				  exprNode_effect (exprData_getPairB (data)));
9330 	  break;
9331 
9332 	case XPR_BLOCK:
9333 	  ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9334 	  break;
9335 
9336 	case XPR_STMT:
9337 	  ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9338 				    exprData_getUopTok (data));
9339 	  break;
9340 
9341 	case XPR_STMTLIST:
9342 	  ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9343 				 exprNode_effect (exprData_getPairB (data)));
9344 	  break;
9345 
9346 	case XPR_FTCASE:
9347 	case XPR_CASE:
9348 	  ret = exprNode_caseMarker
9349 	    (exprNode_effect (exprData_getSingle (data)),
9350 	     TRUE);
9351 	  break;
9352 
9353 	case XPR_FTDEFAULT:
9354 	case XPR_DEFAULT:
9355 	  ret = exprNode_createTok (exprData_getTok (data));
9356 	  break;
9357 
9358 	case XPR_SWITCH:
9359 	  ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9360 				 exprNode_effect (exprData_getPairB (data)));
9361 	  break;
9362 
9363 	case XPR_INIT:
9364 	  ret = exprNode_makeInitialization
9365 	    (exprData_getInitId (data),
9366 	     exprNode_effect (exprData_getInitNode (data)));
9367 	  break;
9368 
9369 	case XPR_FACCESS:
9370 	  ret = exprNode_fieldAccessAux
9371 	    (exprNode_effect (exprData_getFieldNode (data)),
9372 	     exprNode_loc (exprData_getFieldNode (data)),
9373 	     cstring_copy (exprData_getFieldName (data)));
9374 	  break;
9375 
9376 	case XPR_ARROW:
9377 	  ret = exprNode_arrowAccessAux
9378 	    (exprNode_effect (exprData_getFieldNode (data)),
9379 	     exprNode_loc (exprData_getFieldNode (data)),
9380 	     cstring_copy (exprData_getFieldName (data)));
9381 	  break;
9382 
9383 	case XPR_STRINGLITERAL:
9384 	  ret = e;
9385 	  break;
9386 
9387 	case XPR_NUMLIT:
9388 	  ret = e;
9389 	  break;
9390 
9391 	case XPR_NODE:
9392 	  ret = e;
9393 	  break;
9394 	  /*@-branchstate@*/
9395 	}
9396       /*@=branchstate@*/
9397       /*@=observertrans@*/
9398       /*@=exposetrans@*/
9399       /*@=dependenttrans@*/
9400     }
9401 
9402   if (!innerEffect)
9403     {
9404       inEffect = FALSE;
9405     }
9406 
9407   return ret;
9408 }
9409 
exprNode_rootVarName(exprNode e)9410 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9411 {
9412   cstring ret;
9413   exprData data;
9414 
9415   if (exprNode_isError (e))
9416     {
9417       return cstring_undefined;
9418     }
9419 
9420   data = e->edata;
9421 
9422   switch (e->kind)
9423     {
9424     case XPR_PARENS:
9425       ret = exprNode_rootVarName (exprData_getUopNode (data));
9426       break;
9427     case XPR_ASSIGN:
9428       ret = exprNode_rootVarName (exprData_getOpA (data));
9429       break;
9430     case XPR_CONST:
9431     case XPR_VAR:
9432       ret = exprData_getId (data);
9433       break;
9434     case XPR_INIT:
9435       ret = idDecl_getName (exprData_getInitId (data));
9436       break;
9437     case XPR_LABEL:
9438     case XPR_TOK:
9439     case XPR_ITERCALL:
9440     case XPR_EMPTY:
9441     case XPR_CALL:
9442     case XPR_INITBLOCK:
9443     case XPR_BODY:
9444     case XPR_FETCH:
9445     case XPR_OP:
9446     case XPR_POSTOP:
9447     case XPR_PREOP:
9448     case XPR_OFFSETOF:
9449     case XPR_ALIGNOFT:
9450     case XPR_ALIGNOF:
9451     case XPR_SIZEOFT:
9452     case XPR_SIZEOF:
9453     case XPR_VAARG:
9454     case XPR_CAST:
9455     case XPR_ITER:
9456     case XPR_FOR:
9457     case XPR_FORPRED:
9458     case XPR_BREAK:
9459     case XPR_RETURN:
9460     case XPR_NULLRETURN:
9461     case XPR_COMMA:
9462     case XPR_COND:
9463     case XPR_IF:
9464     case XPR_IFELSE:
9465     case XPR_WHILE:
9466     case XPR_WHILEPRED:
9467     case XPR_DOWHILE:
9468     case XPR_GOTO:
9469     case XPR_CONTINUE:
9470     case XPR_FTDEFAULT:
9471     case XPR_DEFAULT:
9472     case XPR_SWITCH:
9473     case XPR_FTCASE:
9474     case XPR_CASE:
9475     case XPR_BLOCK:
9476     case XPR_STMT:
9477     case XPR_STMTLIST:
9478     case XPR_FACCESS:
9479     case XPR_ARROW:
9480     case XPR_NODE:
9481     case XPR_NUMLIT:
9482     case XPR_STRINGLITERAL:
9483       ret = cstring_undefined;
9484       break;
9485     }
9486 
9487   return ret;
9488 }
9489 
exprNode_doUnparse(exprNode e)9490 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9491 {
9492   cstring ret;
9493   exprData data;
9494 
9495   if (exprNode_isError (e))
9496     {
9497       static /*@only@*/ cstring error = cstring_undefined;
9498 
9499       if (!cstring_isDefined (error))
9500 	{
9501 	  error = cstring_makeLiteral ("<error>");
9502 	}
9503 
9504       return error;
9505     }
9506 
9507   data = e->edata;
9508 
9509   switch (e->kind)
9510     {
9511     case XPR_PARENS:
9512       ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9513       break;
9514     case XPR_ASSIGN:
9515       ret = message ("%s %s %s",
9516 		     exprNode_unparse (exprData_getOpA (data)),
9517 		     lltok_unparse (exprData_getOpTok (data)),
9518 		     exprNode_unparse (exprData_getOpB (data)));
9519       break;
9520     case XPR_CALL:
9521       ret = message ("%s(%q)",
9522 		     exprNode_unparse (exprData_getFcn (data)),
9523 		     exprNodeList_unparse (exprData_getArgs (data)));
9524       break;
9525     case XPR_INITBLOCK:
9526       ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9527       break;
9528     case XPR_EMPTY:
9529       ret = cstring_undefined;
9530       break;
9531     case XPR_LABEL:
9532       ret = message ("%s:", exprData_getId (data));
9533       break;
9534     case XPR_CONST:
9535     case XPR_VAR:
9536       ret = cstring_copy (exprData_getId (data));
9537       break;
9538     case XPR_FETCH:
9539       ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9540 		     exprNode_unparse (exprData_getPairB (data)));
9541       break;
9542     case XPR_BODY:
9543       ret = message ("<body>");
9544       break;
9545     case XPR_OP:
9546       ret = message ("%s %s %s",
9547 		     exprNode_unparse (exprData_getOpA (data)),
9548 		     lltok_unparse (exprData_getOpTok (data)),
9549       		     exprNode_unparse (exprData_getOpB (data)));
9550       break;
9551 
9552     case XPR_PREOP:
9553       ret = message ("%s%s",
9554 		     lltok_unparse (exprData_getUopTok (data)),
9555 		     exprNode_unparse (exprData_getUopNode (data)));
9556       break;
9557 
9558     case XPR_POSTOP:
9559       ret = message ("%s%s",
9560 		     exprNode_unparse (exprData_getUopNode (data)),
9561 		     lltok_unparse (exprData_getUopTok (data)));
9562       break;
9563 
9564     case XPR_OFFSETOF:
9565       ret = message ("offsetof(%s,%q)",
9566 		     ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9567 		     cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9568       break;
9569 
9570     case XPR_SIZEOFT:
9571       ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9572       break;
9573 
9574     case XPR_SIZEOF:
9575       ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9576       break;
9577 
9578     case XPR_ALIGNOFT:
9579       ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9580       break;
9581 
9582     case XPR_ALIGNOF:
9583       ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9584       break;
9585 
9586     case XPR_VAARG:
9587       ret = message ("va_arg(%s, %q)",
9588 		     exprNode_unparse (exprData_getCastNode (data)),
9589 		     qtype_unparse (exprData_getCastType (data)));
9590       break;
9591 
9592     case XPR_ITERCALL:
9593       ret = message ("%q(%q)",
9594 		     uentry_getName (exprData_getIterCallIter (data)),
9595 		     exprNodeList_unparse (exprData_getIterCallArgs (data)));
9596       break;
9597     case XPR_ITER:
9598       ret = message ("%q(%q) %s %q",
9599 		     uentry_getName (exprData_getIterSname (data)),
9600 		     exprNodeList_unparse (exprData_getIterAlist (data)),
9601 		     exprNode_unparse (exprData_getIterBody (data)),
9602 		     uentry_getName (exprData_getIterEname (data)));
9603       break;
9604     case XPR_CAST:
9605       ret = message ("(%q)%s",
9606 		     qtype_unparse (exprData_getCastType (data)),
9607 		     exprNode_unparse (exprData_getCastNode (data)));
9608       break;
9609 
9610     case XPR_FOR:
9611       ret = message ("%s %s",
9612 		     exprNode_unparse (exprData_getPairA (data)),
9613 		     exprNode_unparse (exprData_getPairB (data)));
9614       break;
9615 
9616     case XPR_FORPRED:
9617             ret = message ("for (%s; %s; %s)",
9618 		     exprNode_unparse (exprData_getTripleInit (data)),
9619 		     exprNode_unparse (exprData_getTripleTest (data)),
9620 		     exprNode_unparse (exprData_getTripleInc (data)));
9621       break;
9622 
9623     case XPR_GOTO:
9624       ret = message ("goto %s", exprData_getLiteral (data));
9625       break;
9626 
9627     case XPR_CONTINUE:
9628       ret = cstring_makeLiteral ("continue");
9629       break;
9630 
9631     case XPR_BREAK:
9632       ret = cstring_makeLiteral ("break");
9633       break;
9634 
9635     case XPR_RETURN:
9636       ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9637       break;
9638 
9639     case XPR_NULLRETURN:
9640       ret = cstring_makeLiteral ("return");
9641       break;
9642 
9643     case XPR_COMMA:
9644       ret = message ("%s, %s",
9645 		     exprNode_unparse (exprData_getPairA (data)),
9646 		     exprNode_unparse (exprData_getPairB (data)));
9647       break;
9648 
9649     case XPR_COND:
9650       ret = message ("%s ? %s : %s",
9651 		     exprNode_unparse (exprData_getTriplePred (data)),
9652 		     exprNode_unparse (exprData_getTripleTrue (data)),
9653 		     exprNode_unparse (exprData_getTripleFalse (data)));
9654       break;
9655     case XPR_IF:
9656       ret = message ("if (%s) %s",
9657 		     exprNode_unparse (exprData_getPairA (data)),
9658 		     exprNode_unparse (exprData_getPairB (data)));
9659       break;
9660 
9661     case XPR_IFELSE:
9662       ret = message ("if (%s) %s else %s",
9663 		     exprNode_unparse (exprData_getTriplePred (data)),
9664 		     exprNode_unparse (exprData_getTripleTrue (data)),
9665 		     exprNode_unparse (exprData_getTripleFalse (data)));
9666       break;
9667     case XPR_WHILE:
9668       ret = message ("while (%s) %s",
9669 		     exprNode_unparse (exprData_getPairA (data)),
9670 		     exprNode_unparse (exprData_getPairB (data)));
9671       break;
9672 
9673     case XPR_WHILEPRED:
9674       ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9675       break;
9676 
9677     case XPR_TOK:
9678       ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9679       break;
9680 
9681     case XPR_DOWHILE:
9682       ret = message ("do { %s } while (%s)",
9683 		     exprNode_unparse (exprData_getPairB (data)),
9684 		     exprNode_unparse (exprData_getPairA (data)));
9685       break;
9686 
9687     case XPR_BLOCK:
9688       ret = message ("{ %s }", exprNode_unparse (exprData_getSingle (data)));
9689       /* evans 2002-02-20 was unparseFirst! */
9690       break;
9691 
9692     case XPR_STMT:
9693       ret = message ("%s;", exprNode_unparse (exprData_getUopNode (data)));
9694       break;
9695 
9696     case XPR_STMTLIST:
9697       if (exprNode_isStatement (exprData_getPairA (data)))
9698 	{
9699 	  /*
9700 	  ** statement expressions already print the ;
9701 	  */
9702 
9703 	  ret = message ("%s %s",
9704 			 exprNode_unparse (exprData_getPairA (data)),
9705 			 exprNode_unparse (exprData_getPairB (data)));
9706 	}
9707       else
9708 	{
9709 	  ret = message ("%s; %s",
9710 			 exprNode_unparse (exprData_getPairA (data)),
9711 			 exprNode_unparse (exprData_getPairB (data)));
9712 	}
9713       break;
9714 
9715     case XPR_FTDEFAULT:
9716     case XPR_DEFAULT:
9717       ret = cstring_makeLiteral ("default:");
9718       break;
9719 
9720     case XPR_SWITCH:
9721       ret = message ("switch (%s) %s",
9722 		     exprNode_unparse (exprData_getPairA (data)),
9723 		     exprNode_unparse (exprData_getPairB (data)));
9724       break;
9725 
9726     case XPR_FTCASE:
9727     case XPR_CASE:
9728       ret = message ("case %s:",
9729 		     exprNode_unparse (exprData_getSingle (data)));
9730       break;
9731 
9732     case XPR_INIT:
9733       if (exprNode_isError (exprData_getInitNode (data)))
9734 	{
9735 	  ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9736 	}
9737       else
9738 	{
9739 	  ret = message ("%q = %s",
9740 			 idDecl_unparseC (exprData_getInitId (data)),
9741 			 exprNode_unparse (exprData_getInitNode (data)));
9742 	}
9743       break;
9744 
9745     case XPR_FACCESS:
9746       ret = message ("%s.%s",
9747 		     exprNode_unparse (exprData_getFieldNode (data)),
9748 		     exprData_getFieldName (data));
9749       break;
9750 
9751     case XPR_ARROW:
9752             ret = message ("%s->%s",
9753 		     exprNode_unparse (exprData_getFieldNode (data)),
9754 		     exprData_getFieldName (data));
9755       break;
9756 
9757     case XPR_STRINGLITERAL:
9758       if (ctype_isWideString (e->typ))
9759 	{
9760 	  ret = message ("L\"%s\"", exprData_getLiteral (data));
9761 	}
9762       else
9763 	{
9764 	  ret = message ("\"%s\"", exprData_getLiteral (data));
9765 	}
9766       break;
9767 
9768     case XPR_NUMLIT:
9769       ret = cstring_copy (exprData_getLiteral (data));
9770       break;
9771 
9772     case XPR_NODE:
9773       ret = cstring_makeLiteral ("<node>");
9774       break;
9775     }
9776 
9777   return ret;
9778 }
9779 
9780 bool
exprNode_isInitializer(exprNode e)9781 exprNode_isInitializer (exprNode e)
9782 {
9783   return (exprNode_isDefined (e)
9784 	  && e->kind == XPR_INIT);
9785 }
9786 
9787 bool
exprNode_isCharLiteral(exprNode e)9788 exprNode_isCharLiteral (exprNode e)
9789 {
9790   if (exprNode_isDefined (e))
9791     {
9792       return (multiVal_isChar (exprNode_getValue (e)));
9793     }
9794   else
9795     {
9796       return FALSE;
9797     }
9798 }
9799 
9800 bool
exprNode_isNumLiteral(exprNode e)9801 exprNode_isNumLiteral (exprNode e)
9802 {
9803   if (exprNode_isDefined (e))
9804     {
9805       return (multiVal_isInt (exprNode_getValue (e)));
9806     }
9807   else
9808     {
9809       return FALSE;
9810     }
9811 }
9812 
9813 static bool
exprNode_isFalseConstant(exprNode e)9814 exprNode_isFalseConstant (exprNode e)
9815 {
9816   if (exprNode_isDefined (e))
9817     {
9818       cstring s = exprNode_rootVarName (e);
9819 
9820       if (cstring_equal (s, context_getFalseName ()))
9821 	{
9822 	  return TRUE;
9823 	}
9824     }
9825 
9826   return FALSE;
9827 }
9828 
9829 bool
exprNode_matchLiteral(ctype expected,exprNode e)9830 exprNode_matchLiteral (ctype expected, exprNode e)
9831 {
9832   if (exprNode_isDefined (e))
9833     {
9834       multiVal m = exprNode_getValue (e);
9835 
9836       if (multiVal_isDefined (m))
9837 	{
9838 	  if (multiVal_isInt (m))
9839 	    {
9840 	      long int val = multiVal_forceInt (m);
9841 
9842 	      if (ctype_isNumAbstract (expected)
9843 		  && context_flagOn (FLG_NUMABSTRACTLIT, exprNode_loc (e)))
9844 		{
9845 		  return TRUE;
9846 		}
9847 
9848 	      if (ctype_isDirectBool (ctype_realishType (expected)))
9849 		{
9850 		  if (val == 0)
9851 		    {
9852 		      return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9853 		    }
9854 		  else
9855 		    {
9856 		      return FALSE;
9857 		    }
9858 		}
9859 
9860 	      if (ctype_isRealInt (expected))
9861 		{
9862 		  /*
9863 		  ** unsigned <- [ constant >= 0 is okay ]
9864 		  */
9865 
9866 		  if (ctype_isUnsigned (expected))
9867 		    {
9868 		      if (val < 0)
9869 			{
9870 			  return FALSE;
9871 			}
9872 		    }
9873 
9874 		  /*
9875 		  ** No checks on sizes of integers...maybe add
9876 		  ** these later.
9877 		  */
9878 
9879 		  DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9880 		  DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9881 			    bool_unparse (ctype_isInt (exprNode_getType (e)))));
9882 
9883 		  if (context_getFlag (FLG_NUMLITERAL)
9884 		      && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9885 		    return TRUE;
9886 		  } else {
9887 		    if (val == 0) {
9888 		      return TRUE;
9889 		    } else {
9890 		      return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9891 		    }
9892 		  }
9893 		}
9894 	      else if (ctype_isChar (expected))
9895 		{
9896 		  return FALSE;
9897 		}
9898 	      else if (ctype_isArrayPtr (expected))
9899 		{
9900 		  /*
9901 		  ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9902 		  */
9903 
9904 		  if (val == 0)
9905 		    {
9906 		      if (ctype_match (exprNode_getType (e), expected)
9907 			  || ctype_isVoidPointer (exprNode_getType (e)))
9908 			{
9909 			  return TRUE;
9910 			}
9911 		    }
9912 		  else
9913 		    {
9914 		      return FALSE;
9915 		    }
9916 		}
9917 	      else if (ctype_isAnyFloat (expected))
9918 		{
9919 		  return (context_getFlag (FLG_NUMLITERAL));
9920 		}
9921 	      else
9922 		{
9923 		  return FALSE;
9924 		}
9925 	    }
9926 	  else if (multiVal_isDouble (m))
9927 	    {
9928 	      if (ctype_isAnyFloat (expected))
9929 		{
9930 		  return TRUE;
9931 		}
9932 	    }
9933 	  else if (multiVal_isChar (m))
9934 	    {
9935 	      /*signed? */ char val = multiVal_forceChar (m);
9936 
9937 	      if (ctype_isChar (expected))
9938 		{
9939 		  if (ctype_isUnsigned (expected) && ((int) val) < 0)
9940 		    {
9941 		      return FALSE;
9942 		    }
9943 		  else
9944 		    {
9945 		      return TRUE;
9946 		    }
9947 		}
9948 	    }
9949 	  else
9950 	    {
9951 	      return FALSE;
9952 	    }
9953 	}
9954     }
9955 
9956   return FALSE;
9957 }
9958 
9959 bool
exprNode_matchType(ctype expected,exprNode e)9960 exprNode_matchType (ctype expected, exprNode e)
9961 {
9962   ctype actual;
9963 
9964   if (!exprNode_isDefined (e)) return TRUE;
9965 
9966   actual = ctype_realishType (exprNode_getType (e));
9967 
9968   if (ctype_match (ctype_realishType (expected), actual))
9969     {
9970       return TRUE;
9971     }
9972 
9973   llassert (!exprNode_isError (e));
9974   return (exprNode_matchLiteral (expected, e));
9975 }
9976 
9977 static bool
exprNode_matchTypes(exprNode e1,exprNode e2)9978 exprNode_matchTypes (exprNode e1, exprNode e2)
9979 {
9980   ctype t1;
9981   ctype t2;
9982 
9983   if (!exprNode_isDefined (e1)) return TRUE;
9984   if (!exprNode_isDefined (e2)) return TRUE;
9985 
9986   /*
9987   ** realish type --- keep bools, bools
9988   */
9989 
9990   t1 = ctype_realishType (exprNode_getType (e1));
9991   t2 = ctype_realishType (exprNode_getType (e2));
9992 
9993   if (ctype_match (t1, t2))
9994     {
9995       return TRUE;
9996     }
9997 
9998   DPRINTF (("Matching literal! %s %s %s %s",
9999 	    ctype_unparse (t1), exprNode_unparse (e2),
10000 	    ctype_unparse (t2), exprNode_unparse (e1)));
10001 
10002   return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
10003 }
10004 
10005 /*
10006 ** pass e as ct
10007 */
10008 
10009 static bool
exprNode_matchArgType(ctype ct,exprNode e)10010   exprNode_matchArgType (ctype ct, exprNode e)
10011 {
10012   ctype et;
10013 
10014   if (!exprNode_isDefined (e))
10015     {
10016       return TRUE;
10017     }
10018 
10019   et = ctype_realType (exprNode_getType (e));
10020 
10021   if (ctype_matchArg (ct, et)) return TRUE;
10022 
10023   llassert (!exprNode_isError (e));
10024   return (exprNode_matchLiteral (ct, e));
10025 }
10026 
10027 static /*@only@*/ exprNodeSList
exprNode_flatten(exprNode e)10028   exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
10029 {
10030   if (exprNode_isDefined (e))
10031     {
10032       if (e->kind == XPR_STMTLIST)
10033 	{
10034 	  return (exprNodeSList_append
10035 		  (exprNode_flatten (exprData_getPairA (e->edata)),
10036 		   exprNode_flatten (exprData_getPairB (e->edata))));
10037 	}
10038       else if (e->kind == XPR_BLOCK)
10039 	{
10040 	  return (exprNode_flatten (exprData_getSingle (e->edata)));
10041 	}
10042       else
10043 	{
10044 	  return (exprNodeSList_singleton (e));
10045 	}
10046     }
10047 
10048   return exprNodeSList_new ();
10049 }
10050 
10051 static /*@exposed@*/ exprNode
exprNode_lastStatement(exprNode e)10052 exprNode_lastStatement (/*@returned@*/ exprNode e)
10053 {
10054   if (exprNode_isDefined (e))
10055     {
10056       if (e->kind == XPR_STMTLIST)
10057 	{
10058 	  exprNode b = exprData_getPairB (e->edata);
10059 
10060 	  if (exprNode_isDefined (b))
10061 	    {
10062 	      return exprNode_lastStatement (b);
10063 	    }
10064 	  else
10065 	    {
10066 	      return exprNode_lastStatement (exprData_getPairA (e->edata));
10067 	    }
10068 	}
10069       else if (e->kind == XPR_BLOCK)
10070 	{
10071 	  return (exprNode_lastStatement (exprData_getSingle (e->edata)));
10072 	}
10073       else
10074 	{
10075 	  return (e);
10076 	}
10077     }
10078 
10079   return exprNode_undefined;
10080 }
10081 
10082 static /*@exposed@*/ exprNode
exprNode_firstStatement(exprNode e)10083 exprNode_firstStatement (/*@returned@*/ exprNode e)
10084 {
10085   if (exprNode_isDefined (e))
10086     {
10087       if (e->kind == XPR_STMTLIST)
10088 	{
10089 	  exprNode b = exprData_getPairA (e->edata);
10090 
10091 	  if (exprNode_isDefined (b))
10092 	    {
10093 	      return exprNode_firstStatement (b);
10094 	    }
10095 	  else
10096 	    {
10097 	      return exprNode_firstStatement (exprData_getPairB (e->edata));
10098 	    }
10099 	}
10100       else if (e->kind == XPR_BLOCK)
10101 	{
10102 	  return (exprNode_firstStatement (exprData_getSingle (e->edata)));
10103 	}
10104       else
10105 	{
10106 	  return (e);
10107 	}
10108     }
10109 
10110   return exprNode_undefined;
10111 }
10112 
10113 static void
exprNode_mergeUSs(exprNode res,exprNode other)10114 exprNode_mergeUSs (exprNode res, exprNode other)
10115 {
10116   if (exprNode_isDefined (res) && exprNode_isDefined (other))
10117     {
10118       res->msets = sRefSet_union (res->msets, other->msets);
10119       res->sets = sRefSet_union (res->sets, other->sets);
10120       res->uses = sRefSet_union (res->uses, other->uses);
10121     }
10122 }
10123 
10124 static void
exprNode_mergeCondUSs(exprNode res,exprNode other1,exprNode other2)10125 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
10126 {
10127   if (exprNode_isDefined (res))
10128     {
10129       if (exprNode_isDefined (other1))
10130 	{
10131 	  res->sets = sRefSet_union (res->sets, other1->sets);
10132 	  res->msets = sRefSet_union (res->msets, other1->msets);
10133 	  res->uses = sRefSet_union (res->uses, other1->uses);
10134 	}
10135       if (exprNode_isDefined (other2))
10136 	{
10137 	  res->sets = sRefSet_union (res->sets, other2->sets);
10138 	  res->msets = sRefSet_union (res->msets, other2->msets);
10139 	  res->uses = sRefSet_union (res->uses, other2->uses);
10140 	}
10141     }
10142 }
10143 
10144 /*
10145 ** modifies e->uses
10146 **
10147 ** Reports errors is s is not defined.
10148 */
10149 
10150 static void
exprNode_addUse(exprNode e,sRef s)10151 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
10152 {
10153   if (exprNode_isDefined (e))
10154     {
10155       e->uses = sRefSet_insert (e->uses, s);
10156     }
10157 }
10158 
10159 void
exprNode_checkUse(exprNode e,sRef s,fileloc loc)10160 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
10161 {
10162   if (sRef_isKnown (s) && !sRef_isConst (s))
10163     {
10164       /*
10165       ** need to check all outer types are useable
10166       */
10167 
10168       DPRINTF (("Check use: %s / %s",
10169 		exprNode_unparse (e), sRef_unparse (s)));
10170 
10171       exprNode_addUse (e, s);
10172 
10173       if (!context_inProtectVars ())
10174 	{
10175 	  /*
10176 	  ** only report the deepest error
10177 	  */
10178 
10179 	  sRef errorRef = sRef_undefined;
10180 	  sRef lastRef  = sRef_undefined;
10181 	  bool deadRef = FALSE;
10182 	  bool unuseable = FALSE;
10183 	  bool errorMaybe = FALSE;
10184 
10185 	  while (sRef_isValid (s) && sRef_isKnown (s))
10186 	    {
10187 	      ynm readable = sRef_isValidLvalue (s);
10188 
10189 	      DPRINTF (("Readable: %s / %s",
10190 			sRef_unparseFull (s), ynm_unparse (readable)));
10191 
10192 	      if (!(ynm_toBoolStrict (readable)))
10193 		{
10194 		  if (ynm_isMaybe (readable))
10195 		    {
10196 		      lastRef = errorRef;
10197 		      errorRef = s;
10198 		      DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10199 		      deadRef = sRef_isPossiblyDead (errorRef);
10200 		      unuseable = sRef_isUnuseable (errorRef);
10201 		      errorMaybe = TRUE;
10202 		    }
10203 		  else
10204 		    {
10205 		      lastRef = errorRef;
10206 		      errorRef = s;
10207 		      DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10208 		      deadRef = sRef_isDead (errorRef);
10209 		      unuseable = sRef_isUnuseable (errorRef);
10210 		      errorMaybe = FALSE;
10211 		    }
10212 
10213 		  /*
10214 		  if (!sRef_isPartial (s))
10215 		    {
10216 		      DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10217 		      sRef_setDefined (s, loc);
10218 		      DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10219 		    }
10220 		  */
10221 		}
10222 
10223 	      s = sRef_getBaseSafe (s);
10224 	    } /* end while */
10225 
10226 	  if (sRef_isValid (errorRef))
10227 	    {
10228 	      if (sRef_isValid (lastRef) && sRef_isField (lastRef)
10229 		  && sRef_isPointer (errorRef))
10230 		{
10231 		  errorRef = lastRef;
10232 		  DPRINTF (("errorRef: %s", sRef_unparseFull (errorRef)));
10233 		}
10234 
10235 	      if (deadRef)
10236 		{
10237 		  if (sRef_isThroughArrayFetch (errorRef))
10238 		    {
10239 		      if (optgenerror
10240 			  (FLG_STRICTUSERELEASED,
10241 			   message ("%q %q may be used after being released",
10242 				    sRef_unparseKindNamePlain (errorRef),
10243 				    sRef_unparse (errorRef)),
10244 			   loc))
10245 			{
10246 			  sRef_showRefKilled (errorRef);
10247 
10248 			  if (sRef_isKept (errorRef))
10249 			    {
10250 			      sRef_clearAliasState (errorRef, loc);
10251 			    }
10252 			}
10253 		    }
10254 		  else
10255 		    {
10256 		      DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10257 
10258 		      if (optgenerror
10259 			  (FLG_USERELEASED,
10260 			   message ("%q %q %qused after being released",
10261 				    sRef_unparseKindNamePlain (errorRef),
10262 				    sRef_unparse (errorRef),
10263 				    cstring_makeLiteral (errorMaybe
10264 							 ? "may be " : "")),
10265 			   loc))
10266 			{
10267 			  sRef_showRefKilled (errorRef);
10268 
10269 			  if (sRef_isKept (errorRef))
10270 			    {
10271 			      sRef_clearAliasState (errorRef, loc);
10272 			    }
10273 			}
10274 		    }
10275 		}
10276 	      else if (unuseable)
10277 		{
10278 		  if (optgenerror
10279 		      (FLG_USEDEF,
10280 		       message ("%q %q%qused in inconsistent state",
10281 				sRef_unparseKindName (errorRef),
10282 				sRef_unparseOpt (errorRef),
10283 				cstring_makeLiteral (errorMaybe ? "may be " : "")),
10284 		       loc))
10285 		    {
10286 		      sRef_showStateInconsistent (errorRef);
10287 		    }
10288 		}
10289 	      else
10290 		{
10291 		  DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10292 
10293 		  if (optgenerror
10294 		      (FLG_USEDEF,
10295 		       message ("%q %q%qused before definition",
10296 				sRef_unparseKindName (errorRef),
10297 				sRef_unparseOpt (errorRef),
10298 				cstring_makeLiteral (errorMaybe ? "may be " : "")),
10299 		       loc))
10300 		    {
10301 		      ;
10302 		    }
10303 
10304 		  DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10305 		}
10306 
10307 	      sRef_setDefined (errorRef, loc);
10308 
10309 	      if (sRef_isAddress (errorRef))
10310 		{
10311 		  sRef_setDefined (sRef_getRootBase (errorRef), loc);
10312 		}
10313 	    } /* end is error */
10314 	}
10315     }
10316 
10317   setCodePoint ();
10318 }
10319 
10320 static void
checkSafeUse(exprNode e,sRef s)10321 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10322 {
10323   if (exprNode_isDefined (e) && sRef_isKnown (s))
10324     {
10325       e->uses = sRefSet_insert (e->uses, s);
10326     }
10327 }
10328 
10329 static void
exprNode_checkSetAny(exprNode e,cstring name)10330 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10331 {
10332   if (exprNode_isDefined (e))
10333     {
10334       e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10335     }
10336 }
10337 
10338 void
exprNode_checkSet(exprNode e,sRef s)10339 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10340 {
10341   sRef defines = sRef_undefined;
10342 
10343   if (sRef_isValid (s) && !sRef_isNothing (s))
10344     {
10345       uentry ue = sRef_getBaseUentry (s);
10346 
10347       if (uentry_isValid (ue))
10348 	{
10349 	  uentry_setLset (ue);
10350 	}
10351 
10352       if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10353 	{
10354 	  voptgenerror (FLG_USEDEF,
10355 			message ("Attempt to set unuseable storage: %q",
10356 				 sRef_unparse (s)),
10357 			exprNode_loc (e));
10358 	}
10359 
10360       if (sRef_isMeaningful (s))
10361 	{
10362 	  if (sRef_isDead (s))
10363 	    {
10364 	      sRef base = sRef_getBaseSafe (s);
10365 
10366 	      if (sRef_isValid (base)
10367 		  && sRef_isDead (base))
10368 		{
10369 		  sRef_setPartial (s, exprNode_loc (e));
10370 		}
10371 
10372 	      defines = s; /* okay - modifies for only param */
10373 	    }
10374 	  else if (sRef_isPartial (s))
10375 	    {
10376 	      sRef eref = exprNode_getSref (e);
10377 
10378 	      if (!sRef_isPartial (eref))
10379 		{
10380 		  /*
10381 	          ** should do something different here???
10382 		  */
10383 
10384 		  sRef_setDefinedComplete (eref, exprNode_loc (e));
10385 		}
10386 	      else
10387 		{
10388 		  sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10389 		}
10390 
10391 	      if (sRef_isMeaningful (eref))
10392 		{
10393 		  defines = eref;
10394 		}
10395 	      else
10396 		{
10397 		  defines = s;
10398 		}
10399 	    }
10400 	  else if (sRef_isAllocated (s))
10401 	    {
10402 	      sRef eref = exprNode_getSref (e);
10403 
10404 
10405 	      if (!sRef_isAllocated (eref))
10406 		{
10407 		  sRef_setDefinedComplete (eref, exprNode_loc (e));
10408 		}
10409 	      else
10410 		{
10411 		  sRef base = sRef_getBaseSafe (eref);
10412 
10413 		  if (sRef_isValid (base))
10414 		    {
10415 		      sRef_setPdefined (base, exprNode_loc (e));
10416 		    }
10417 		}
10418 
10419 	      defines = s;
10420 	    }
10421 	  else
10422 	    {
10423 	      sRef_setDefinedNCComplete (s, exprNode_loc (e));
10424 	      defines = s;
10425 	    }
10426 
10427 	}
10428       else /* not meaningful...but still need to insert it */
10429 	{
10430 	  defines = s;
10431 	}
10432     }
10433 
10434   if (exprNode_isDefined (e) && sRef_isValid (defines))
10435     {
10436       e->sets = sRefSet_insert (e->sets, defines);
10437     }
10438 }
10439 
10440 void
exprNode_checkMSet(exprNode e,sRef s)10441 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10442 {
10443   if (sRef_isValid (s) && !sRef_isNothing (s))
10444     {
10445       uentry ue = sRef_getBaseUentry (s);
10446 
10447       if (uentry_isValid (ue))
10448 	{
10449 	  uentry_setLset (ue);
10450 	}
10451 
10452       if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10453 	{
10454 	  voptgenerror (FLG_USEDEF,
10455 			message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10456 			exprNode_loc (e));
10457 	}
10458 
10459       if (sRef_isMeaningful (s))
10460 	{
10461 	  sRef_setDefinedComplete (s, exprNode_loc (e));
10462 	}
10463 
10464       if (exprNode_isDefined (e))
10465 	{
10466 	  e->msets = sRefSet_insert (e->msets, s);
10467 	}
10468     }
10469 }
10470 
10471 static void
checkUnspecCall(exprNode fcn,uentryList params,exprNodeList args)10472 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10473 {
10474   checkAnyCall (fcn, cstring_undefined, params, args,
10475 		FALSE, sRefSet_undefined, FALSE, 0);
10476 }
10477 
10478 static void
checkOneArg(uentry ucurrent,exprNode current,exprNode fcn,bool isSpec,int argno,int totargs)10479 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10480 	     /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10481 {
10482   setCodePoint ();
10483 
10484   if (uentry_isYield (ucurrent))
10485     {
10486       sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10487       exprNode_checkSet (current, current->sref);
10488     }
10489   else
10490     {
10491       if (uentry_isSefParam (ucurrent))
10492 	{
10493 	  sRefSet sets = current->sets;
10494 	  sRef ref = exprNode_getSref (current);
10495 
10496 	  if (sRef_isMacroParamRef (ref))
10497 	    {
10498 	      uentry ue = sRef_getUentry (ref);
10499 
10500 	      if (!uentry_isSefParam (ue))
10501 		{
10502 		  voptgenerror
10503 		    (FLG_SEFPARAMS,
10504 		     message
10505 		     ("Parameter %d to %s is declared sef, but "
10506 		      "the argument is a macro parameter declared "
10507 		      "without sef: %s",
10508 		      argno, exprNode_unparse (fcn),
10509 		      exprNode_unparse (current)),
10510 		     exprNode_loc (current));
10511 		}
10512 	    }
10513 
10514 	  if (!sRefSet_isEmpty (sets))
10515 	    {
10516 	      sRefSet reported = sRefSet_undefined;
10517 
10518 	      sRefSet_realElements (current->sets, el)
10519 		{
10520 		  if (sRefSet_isSameNameMember (reported, el))
10521 		    {
10522 		      ; /* don't report again */
10523 		    }
10524 		  else
10525 		    {
10526 		      if (sRef_isUnconstrained (el))
10527 			{
10528 			  voptgenerror
10529 			    (FLG_SEFUNSPEC,
10530 			     message
10531 			     ("Parameter %d to %s is declared sef, but "
10532 			      "the argument calls unconstrained function %s "
10533 			      "(no guarantee it will not modify something): %s",
10534 			      argno, exprNode_unparse (fcn),
10535 			      sRef_unconstrainedName (el),
10536 			      exprNode_unparse (current)),
10537 			     exprNode_loc (current));
10538 			}
10539 		      else
10540 			{
10541 			  voptgenerror
10542 			    (FLG_SEFPARAMS,
10543 			     message
10544 			     ("Parameter %d to %s is declared sef, but "
10545 			      "the argument may modify %q: %s",
10546 			      argno, exprNode_unparse (fcn),
10547 			      sRef_unparse (el),
10548 			      exprNode_unparse (current)),
10549 			     exprNode_loc (current));
10550 			}
10551 		    }
10552 		} end_sRefSet_realElements;
10553 	    }
10554 	}
10555 
10556       transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10557       exprNode_mergeUSs (fcn, current);
10558     }
10559 }
10560 
10561 static void
checkAnyCall(exprNode fcn,cstring fname,uentryList pn,exprNodeList args,bool hasMods,sRefSet mods,bool isSpec,int specialArgs)10562   checkAnyCall (/*@dependent@*/ exprNode fcn,
10563 		/*@dependent@*/ cstring fname,
10564 		uentryList pn,
10565 		exprNodeList args,
10566 		bool hasMods, sRefSet mods,
10567 		bool isSpec,
10568 		int specialArgs)
10569 {
10570   int paramno = 0;
10571   int nargs = exprNodeList_size (args);
10572 
10573   setCodePoint ();
10574 
10575   /*
10576   ** concat all args ud's to f, add each arg sref as a use unless
10577   ** it was specified as "out", in which case it is a def.
10578   */
10579 
10580   uentryList_reset (pn);
10581 
10582   /*
10583   ** aliasing checks:
10584   **
10585   **    if paramn is only or unique, no other arg may alias argn
10586   */
10587 
10588   exprNodeList_elements (args, current)
10589     {
10590       paramno++;
10591 
10592       if (exprNode_isDefined (current))
10593 	{
10594 	  if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10595 	    {
10596 	      uentry ucurrent = uentryList_current (pn);
10597 
10598 	      if (specialArgs == 0
10599 		  || (paramno < specialArgs))
10600 		{
10601 		  checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10602 
10603 		  if (context_maybeSet (FLG_ALIASUNIQUE))
10604 		    {
10605 		      if (uentry_isOnly (ucurrent)
10606 			  || uentry_isUnique (ucurrent))
10607 			{
10608 			  checkUniqueParams (fcn, current, args,
10609 					     paramno, ucurrent);
10610 			}
10611 		    }
10612 		}
10613 	    }
10614 	  else /* uentry is undefined */
10615 	    {
10616 	      if (specialArgs == 0)
10617 		{
10618 		  exprNode_checkUseParam (current);
10619 		}
10620 
10621 	      exprNode_mergeUSs (fcn, current);
10622 	    }
10623 	}
10624       uentryList_advanceSafe (pn);
10625     } end_exprNodeList_elements;
10626 
10627   if (hasMods)
10628     {
10629       setCodePoint ();
10630 
10631       sRefSet_allElements (mods, s)
10632 	{
10633 	  sRef fb;
10634 	  sRef rb = sRef_getRootBase (s);
10635 
10636 	  if (sRef_isFileOrGlobalScope (rb))
10637 	    {
10638 	      context_usedGlobal (rb);
10639 	    }
10640 
10641 	  fb = sRef_fixBaseParam (s, args);
10642 
10643 	  if (!sRef_isMacroParamRef (fb))
10644 	    {
10645 	      if (sRef_isNothing (fb))
10646 		{
10647 		  ;
10648 		}
10649 	      else
10650 		{
10651 		  if (sRef_isValid (fb))
10652 		    {
10653 		      uentry ue = sRef_getBaseUentry (s);
10654 
10655 		      if (uentry_isValid (ue))
10656 			{
10657 			  uentry_setLset (ue);
10658 			}
10659 		    }
10660 
10661 		  fcn->sets = sRefSet_insert (fcn->sets, fb);
10662 		}
10663 	    }
10664 	  sRef_clearDerivedComplete (s);
10665 	} end_sRefSet_allElements;
10666 
10667       setCodePoint ();
10668     }
10669   else
10670     {
10671       if (context_hasMods ())
10672 	{
10673 	  if (context_maybeSet (FLG_MODUNCON))
10674 	    {
10675 	      voptgenerror
10676 		(FLG_MODUNCON,
10677 		 message ("Undetected modification possible "
10678 			  "from call to unconstrained function %s: %s",
10679 			  fname,
10680 			  exprNode_unparse (fcn)),
10681 		 exprNode_loc (fcn));
10682 	    }
10683 	}
10684       else
10685 	{
10686 	  if (context_maybeSet (FLG_MODUNCONNOMODS)
10687 	      && !(context_inIterDef () || context_inIterEnd ()))
10688 	    {
10689 	      voptgenerror
10690 		(FLG_MODUNCONNOMODS,
10691 		 message ("Undetected modification possible "
10692 			  "from call to unconstrained function %s: %s",
10693 			  fname,
10694 			  exprNode_unparse (fcn)),
10695 		 exprNode_loc (fcn));
10696 	    }
10697 	}
10698 
10699       exprNode_checkSetAny (fcn, fname);
10700     }
10701 }
10702 
exprNode_checkUseParam(exprNode current)10703 void exprNode_checkUseParam (exprNode current)
10704 {
10705   if (exprNode_isDefined (current))
10706     {
10707       exprNode_checkUse (current, current->sref, current->loc);
10708     }
10709 }
10710 
10711 static ctype
checkNumerics(ctype tr1,ctype tr2,ctype te1,ctype te2,exprNode e1,exprNode e2,lltok op)10712   checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10713 		 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10714 		 lltok op)
10715 {
10716   ctype ret = tr1;
10717 
10718   if (!ctype_match (tr1, tr2))
10719     {
10720       if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10721 	  (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10722 	{
10723 	  DPRINTF (("No error: [%s] %s / [%s]  %s",
10724 		    exprNode_unparse (e1), ctype_unparse (tr1),
10725 		    exprNode_unparse (e2), ctype_unparse (tr2)));
10726 
10727 	  /*
10728 	  ** evans 2003-06-15: changed this so if either type is a literal,
10729 	  **    the other type is used.
10730 	  **    (Need to look at the ISO C99 rules on this...)
10731 	  */
10732 
10733 	  if (exprNode_isNumLiteral (e1)) {
10734 	    ret = tr2;
10735 	  } else if (exprNode_isNumLiteral (e2)) {
10736 	    ret = tr1;
10737 	  } else {
10738 	    ret = ctype_biggerType (tr1, tr2);
10739 	  }
10740 	}
10741       else
10742 	{
10743 	  if (ctype_isNumAbstract (tr1)
10744 	      && exprNode_isNumLiteral (e2)
10745 	      && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10746 	    {
10747 	      ret = tr1; /* No error */
10748 	    }
10749 	  else if (ctype_isNumAbstract (tr2)
10750 		   && exprNode_isNumLiteral (e1)
10751 		   && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10752 	    {
10753 	      ret = tr2;
10754 	    }
10755 	  else
10756 	    {
10757 	      if (gentypeerror
10758 		  (tr1, e1, tr2, e2,
10759 		   message ("Incompatible types for %s (%s, %s): %s %s %s",
10760 			    lltok_unparse (op),
10761 			    ctype_unparse (te1),
10762 			    ctype_unparse (te2),
10763 			    exprNode_unparse (e1), lltok_unparse (op),
10764 			    exprNode_unparse (e2)),
10765 		   e1->loc))
10766 		{
10767 		  ret = ctype_unknown;
10768 		}
10769 	      else
10770 		{
10771 		  ret = ctype_biggerType (tr1, tr2);
10772 		}
10773 	    }
10774 	}
10775     }
10776   else
10777     {
10778       if (ctype_isNumAbstract (tr1))
10779 	{
10780 	  ret = tr1;
10781 	}
10782       else if (ctype_isForceRealNumeric (&tr1)
10783 	       && ctype_isForceRealNumeric (&tr2))
10784 	{
10785 	  ret = ctype_resolveNumerics (tr1, tr2);
10786 	}
10787       else if (!context_msgStrictOps ())
10788 	{
10789 	  if (ctype_isPointer (tr1))
10790 	    {
10791 	      if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10792 		{
10793 		  ret = ctype_int;
10794 		}
10795 	      else if (ctype_isInt (tr2))
10796 		{
10797 		  ret = te1;
10798 		}
10799 	      else
10800 		{
10801 		  ret = ctype_unknown;
10802 		}
10803 	    }
10804 	  else if (ctype_isPointer (tr2))
10805 	    {
10806 	      if (ctype_isPointer (tr1))
10807 		{
10808 		  ret = ctype_int;
10809 		}
10810 	      else if (ctype_isInt (tr1))
10811 		{
10812 		  ret = te2;
10813 		}
10814 	      else
10815 		{
10816 		  ret = ctype_unknown;
10817 		}
10818 	    }
10819 	  else
10820 	    {
10821 	      ret = ctype_resolveNumerics (tr1, tr2);
10822 	    }
10823 	}
10824       else
10825 	{
10826 	  int opid = lltok_getTok (op);
10827 	  bool comparop = (opid == EQ_OP || opid == NE_OP
10828 			   || opid == TLT || opid == TGT
10829 			   || opid == LE_OP || opid == GE_OP);
10830 
10831 	  if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10832 	    {
10833 	      if (comparop
10834 		  && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10835 		      || (ctype_isBool (tr1) && ctype_isBool (tr2))
10836 		      || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10837 		{
10838 		  ; /* no error */
10839 		}
10840 	      else
10841 		{
10842 		  if (ctype_sameName (te1, te2))
10843 		    {
10844 		      voptgenerror
10845 			(FLG_STRICTOPS,
10846 			 message ("Operands of %s are non-numeric (%t): %s %s %s",
10847 				  lltok_unparse (op), te1,
10848 				  exprNode_unparse (e1), lltok_unparse (op),
10849 				  exprNode_unparse (e2)),
10850 			 e1->loc);
10851 		    }
10852 		  else
10853 		    {
10854 		      voptgenerror
10855 			(FLG_STRICTOPS,
10856 			 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10857 				  lltok_unparse (op), te1, te2,
10858 				  exprNode_unparse (e1), lltok_unparse (op),
10859 				  exprNode_unparse (e2)),
10860 			 e1->loc);
10861 		    }
10862 		}
10863 	    }
10864 	  else if (!ctype_isNumeric (tr1))
10865 	    {
10866 	      voptgenerror
10867 		(FLG_STRICTOPS,
10868 		 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10869 			  lltok_unparse (op), te1,
10870 			  exprNode_unparse (e1), lltok_unparse (op),
10871 			  exprNode_unparse (e2)),
10872 		 e1->loc);
10873 	    }
10874 	  else
10875 	    {
10876 	      if (!ctype_isNumeric (tr2))
10877 		{
10878 		  voptgenerror
10879 		    (FLG_STRICTOPS,
10880 		     message ("Left operand of %s is non-numeric (%t): %s %s %s",
10881 			      lltok_unparse (op), te2,
10882 			      exprNode_unparse (e1), lltok_unparse (op),
10883 			      exprNode_unparse (e2)),
10884 		     e2->loc);
10885 		}
10886 	    }
10887 
10888 	  ret = ctype_unknown;
10889 	}
10890     }
10891 
10892   return ret;
10893 }
10894 
10895 static bool
abstractOpError(ctype tr1,ctype tr2,lltok op,exprNode e1,exprNode e2,fileloc loc1,fileloc loc2)10896 abstractOpError (ctype tr1, ctype tr2, lltok op,
10897 		 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10898 		 fileloc loc1, fileloc loc2)
10899 {
10900   if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10901     {
10902       if (ctype_match (tr1, tr2))
10903 	{
10904 	  if (ctype_isRealNumAbstract (tr1))
10905 	    {
10906 	      ; /* No warning for numabstract types */
10907 	    }
10908 	  else
10909 	    {
10910 	      if (lltok_isEqOp (op) || lltok_isNotEqOp (op))
10911 		{
10912 		  return optgenerror
10913 		    (FLG_ABSTRACTCOMPARE,
10914 		     message ("Object equality comparison (%s) on objects of abstract type (%t): %s %s %s",
10915 			      lltok_unparse (op), tr1,
10916 			      exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10917 		     loc1);
10918 		}
10919 	      else
10920 		{
10921 		  return optgenerror
10922 		    (FLG_ABSTRACT,
10923 		     message ("Operands of %s are abstract type (%t): %s %s %s",
10924 			      lltok_unparse (op), tr1,
10925 			      exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10926 		     loc1);
10927 		}
10928 	    }
10929 	}
10930       else
10931 	{
10932 	  if (ctype_isRealNumAbstract (tr1) && ctype_isRealNumAbstract (tr2))
10933 	    {
10934 	      return optgenerror
10935 		(FLG_NUMABSTRACT,
10936 		 message
10937 		 ("Operands of %s are different numabstract types (%t, %t): %s %s %s",
10938 		  lltok_unparse (op), tr1, tr2,
10939 		  exprNode_unparse (e1),
10940 		  lltok_unparse (op), exprNode_unparse (e2)),
10941 		 loc1);
10942 	    }
10943 	  else
10944 	    {
10945 	      return optgenerror
10946 		(FLG_ABSTRACT,
10947 		 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10948 			  lltok_unparse (op), tr1, tr2,
10949 			  exprNode_unparse (e1), lltok_unparse (op),
10950 			  exprNode_unparse (e2)),
10951 		 loc1);
10952 	    }
10953 	}
10954     }
10955   else if (ctype_isRealAbstract (tr1) && !ctype_isRealNumAbstract (tr1))
10956     {
10957       return optgenerror
10958 	(FLG_ABSTRACT,
10959 	 message ("Left operand of %s is abstract type (%t): %s %s %s",
10960 		  lltok_unparse (op), tr1,
10961 		  exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10962 	 loc1);
10963     }
10964   else
10965     {
10966       if (ctype_isRealAbstract (tr2) && !ctype_isRealNumAbstract (tr2))
10967 	{
10968 	  return optgenerror
10969 	    (FLG_ABSTRACT,
10970 	     message ("Right operand of %s is abstract type (%t): %s %s %s",
10971 		      lltok_unparse (op), tr2,
10972 		      exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10973 	     loc2);
10974 	}
10975     }
10976 
10977   return FALSE;
10978 }
10979 
10980 /*
10981 ** e1 <= e2
10982 **
10983 ** requies e1 and e2 and not error exprNode's.
10984 **
10985 ** Checks:
10986 **
10987 **    If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10988 **    the rep of the abstract type is exposed.
10989 **
10990 ** The order is very important:
10991 **
10992 **    check rep expose (move into check transfer)
10993 **    check transfer
10994 **    setup aliases
10995 */
10996 
10997 /*
10998 ** This isn't really a sensible procedure, but the indententation
10999 ** was getting too deep.
11000 */
11001 
11002 static void
checkOneRepExpose(sRef ysr,sRef base,exprNode e1,exprNode e2,ctype ct,sRef s2b)11003 checkOneRepExpose (sRef ysr, sRef base,
11004 		   /*@notnull@*/ exprNode e1,
11005 		   /*@notnull@*/ exprNode e2, ctype ct,
11006 		   sRef s2b)
11007 {
11008   if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
11009 	|| sRef_isOwned (ysr)
11010 	|| sRef_isExposed (ysr)))
11011     {
11012       if (sRef_isAnyParam (base) && !sRef_isExposed (base)
11013 	  && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
11014 
11015 	{
11016 	  if (sRef_isIReference (ysr))
11017 	    {
11018 	      if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11019 		{
11020 		  voptgenerror
11021 		    (FLG_ASSIGNEXPOSE,
11022 		     message
11023 		     ("Assignment of mutable component of parameter %q "
11024 		      "to component of abstract "
11025 		      "type %s exposes rep: %s = %s",
11026 		      sRef_unparse (base),
11027 		      ctype_unparse (ct),
11028 		      exprNode_unparse (e1), exprNode_unparse (e2)),
11029 		     e1->loc);
11030 		}
11031 	      else
11032 		{
11033 		  voptgenerror
11034 		    (FLG_ASSIGNEXPOSE,
11035 		     message
11036 		     ("Assignment of mutable component of parameter %q "
11037 		      "(through alias %q) to component of abstract "
11038 		      "type %s exposes rep: %s = %s",
11039 		      sRef_unparse (base),
11040 		      sRef_unparse (e2->sref),
11041 		      ctype_unparse (ct),
11042 		      exprNode_unparse (e1), exprNode_unparse (e2)),
11043 		     e1->loc);
11044 		}
11045 	    }
11046 	  else
11047 	    {
11048 	      if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11049 		{
11050 		  voptgenerror
11051 		    (FLG_ASSIGNEXPOSE,
11052 		     message ("Assignment of mutable parameter %q "
11053 			      "to component of abstract type %s "
11054 			      "exposes rep: %s = %s",
11055 			      sRef_unparse (base),
11056 			      ctype_unparse (ct),
11057 			      exprNode_unparse (e1),
11058 			      exprNode_unparse (e2)),
11059 		     e1->loc);
11060 		}
11061 	      else
11062 		{
11063 		  voptgenerror
11064 		    (FLG_ASSIGNEXPOSE,
11065 		     message ("Assignment of mutable parameter %q "
11066 			      "(through alias %q) to "
11067 			      "component of abstract type %s exposes "
11068 			      "rep: %s = %s",
11069 			      sRef_unparse (base),
11070 			      sRef_unparse (e2->sref),
11071 			      ctype_unparse (ct),
11072 			      exprNode_unparse (e1),
11073 			      exprNode_unparse (e2)),
11074 		     e1->loc);
11075 		}
11076 	    }
11077 	}
11078 
11079       if (sRef_isFileOrGlobalScope (s2b))
11080 	{
11081 	  if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11082 	    {
11083 	      voptgenerror
11084 		(FLG_REPEXPOSE,
11085 		 message ("Assignment of global %q "
11086 			  "to component of "
11087 			  "abstract type %s exposes rep: %s = %s",
11088 			  sRef_unparse (base),
11089 			  ctype_unparse (ct),
11090 			  exprNode_unparse (e1), exprNode_unparse (e2)),
11091 		 e1->loc);
11092 	    }
11093 	  else
11094 	    {
11095 	      voptgenerror
11096 		(FLG_REPEXPOSE,
11097 		 message ("Assignment of global %q (through alias %q) "
11098 			  "to component of "
11099 			  "abstract type %s exposes rep: %s = %s",
11100 			  sRef_unparse (base),
11101 			  sRef_unparse (e2->sref),
11102 			  ctype_unparse (ct),
11103 			  exprNode_unparse (e1), exprNode_unparse (e2)),
11104 		 e1->loc);
11105 	    }
11106 	}
11107     }
11108 }
11109 
11110 static void
doAssign(exprNode e1,exprNode e2,bool isInit)11111 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
11112 {
11113   DPRINTF (("Do assign: %s <- %s",
11114 	    exprNode_unparse (e1), exprNode_unparse (e2)));
11115   DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
11116 
11117   if (ctype_isRealFunction (exprNode_getType (e1))
11118       && !ctype_isRealPointer (exprNode_getType (e1)))
11119     {
11120       voptgenerror
11121 	(FLG_TYPE,
11122 	 message ("Invalid left-hand side of assignment (function type %s): %s",
11123 		  ctype_unparse (exprNode_getType (e1)),
11124 		  exprNode_unparse (e1)),
11125 	 e1->loc);
11126     }
11127 
11128   if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
11129     {
11130       ctype t2 = exprNode_getType (e2);
11131       sRef sr = sRef_getRootBase (e1->sref);
11132       ctype ct = sRef_getType (sr);
11133 
11134       if (ctype_isAbstract (t2)
11135 	  && !ctype_isNumAbstract (t2)
11136 	  && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
11137 	{
11138 	  /* it is immutable, okay to reference */
11139 	  goto donerepexpose;
11140 	}
11141 
11142       if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
11143 	{
11144 	  sRef s2b = sRef_getRootBase (e2->sref);
11145 	  sRef s1 = e1->sref;
11146 	  sRef s1b = sRef_getRootBase (s1);
11147 	  sRefSet aliases;
11148 
11149 	  aliases = usymtab_canAlias (e2->sref);
11150 
11151 	  if (!sRef_similar (s2b, s1b)
11152 	      && !sRef_isExposed (s1)
11153 	      && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
11154 	    {
11155 	      if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
11156 		  && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
11157 		  && !sRef_isExposed (s2b))
11158 		{
11159 		  if (sRef_isIReference (e2->sref))
11160 		    {
11161 		      voptgenerror
11162 			(FLG_ASSIGNEXPOSE,
11163 			 message
11164 			 ("Assignment of mutable component of parameter %q "
11165 			  "to component of abstract type %s exposes rep: %s = %s",
11166 			  sRef_unparse (s2b),
11167 			  ctype_unparse (ct),
11168 			  exprNode_unparse (e1), exprNode_unparse (e2)),
11169 			 e1->loc);
11170 		    }
11171 		  else
11172 		    {
11173 		      voptgenerror
11174 			(FLG_ASSIGNEXPOSE,
11175 			 message ("Assignment of mutable parameter %q to "
11176 				  "component of abstract type %s exposes rep: %s = %s",
11177 				  sRef_unparse (s2b),
11178 				  ctype_unparse (ct),
11179 				  exprNode_unparse (e1), exprNode_unparse (e2)),
11180 			 e1->loc);
11181 		    }
11182 		}
11183 
11184 	      if (sRef_isFileOrGlobalScope (s2b))
11185 		{
11186 		  voptgenerror
11187 		    (FLG_ASSIGNEXPOSE,
11188 		     message ("Assignment of global %q to component of "
11189 			      "abstract type %s exposes rep: %s = %s",
11190 			      sRef_unparse (s2b),
11191 			      ctype_unparse (ct),
11192 			      exprNode_unparse (e1), exprNode_unparse (e2)),
11193 		     e1->loc);
11194 		}
11195 
11196 	      sRefSet_realElements (aliases, ysr)
11197 		{
11198 		  sRef base = sRef_getRootBase (ysr);
11199 
11200 		  if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
11201 		      || sRef_sameName (base, s1b))
11202 		    {
11203 		     ; /* error already reported or same sref */
11204 		    }
11205 		  else
11206 		    {
11207 		      checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
11208 		    }
11209 		} end_sRefSet_realElements;
11210 	    }
11211 	  sRefSet_free (aliases);
11212 	}
11213     }
11214 
11215  donerepexpose:
11216 
11217   /*
11218   ** function variables don't really work...
11219   */
11220 
11221   if (!ctype_isFunction (ctype_realType (e2->typ)))
11222     {
11223       if (isInit)
11224 	{
11225 	    DPRINTF (("Check init: %s / %s",
11226 		      exprNode_unparse (e1), exprNode_unparse (e2)));
11227 	  transferChecks_initialization (e1, e2);
11228 	}
11229       else
11230 	{
11231 	  transferChecks_assign (e1, e2);
11232 	}
11233     }
11234   else
11235     {
11236       sRef fref = e2->sref;
11237 
11238       sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
11239       sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
11240 
11241             /* Need to typecheck the annotation on the parameters */
11242 
11243       if (ctype_isRealFunction (e1->typ)) {
11244 	uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
11245 	uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
11246 
11247 	if (!uentryList_isMissingParams (e1p)
11248 	    && !uentryList_isMissingParams (e2p)
11249 	    && uentryList_size (e1p) > 0) {
11250 	  if (uentryList_size (e1p) == uentryList_size (e2p)) {
11251 	    int n = 0;
11252 
11253 	    uentryList_elements (e1p, el1) {
11254 	      uentry el2;
11255 
11256 	      el2 = uentryList_getN (e2p, n);
11257 	      n++;
11258 	      uentry_checkMatchParam (el1, el2, n, e2);
11259 	    } end_uentryList_elements;
11260 	  }
11261 	}
11262       }
11263     }
11264 
11265   if (exprNode_isStringLiteral (e2))
11266     {
11267       exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
11268     }
11269 
11270   if (isInit && sRef_isFileOrGlobalScope (e1->sref))
11271     {
11272        ;
11273     }
11274   else
11275     {
11276       DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
11277       updateAliases (e1, e2);
11278     }
11279 }
11280 
11281 static void
checkMacroParen(exprNode e)11282 checkMacroParen (exprNode e)
11283 {
11284   if (exprNode_isError (e) || e->kind == XPR_CAST)
11285     {
11286      ;
11287     }
11288   else
11289     {
11290       if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
11291 	{
11292 	  voptgenerror
11293 	    (FLG_MACROPARENS,
11294 	     message ("Macro parameter used without parentheses: %s",
11295 		      exprNode_unparse (e)),
11296 	     e->loc);
11297 	}
11298     }
11299 }
11300 
11301 static void
reflectNullTest(exprNode e,bool isnull)11302 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
11303 {
11304   if (isnull)
11305     {
11306       e->guards = guardSet_addTrueGuard (e->guards, e->sref);
11307     }
11308   else
11309     {
11310       e->guards = guardSet_addFalseGuard (e->guards, e->sref);
11311     }
11312 }
11313 
11314 /*
11315 ** e1 <= e2
11316 **
11317 ** if e2 is a parameter or global derived location which
11318 ** can be modified (that is, e2 is a mutable abstract type,
11319 ** or a derived pointer), then e1 can alias e2.
11320 **
11321 ** e1 can alias everything which e2 can alias.
11322 **
11323 ** Also, if e1 is guarded, remove from guard sets!
11324 */
11325 
updateAliases(exprNode e1,exprNode e2)11326 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
11327 {
11328   if (!context_inProtectVars ())
11329     {
11330       /*
11331       ** depends on types of e1 and e2
11332       */
11333 
11334       sRef s1 = e1->sref;
11335       sRef s2 = e2->sref;
11336       ctype t1 = exprNode_getType (e1);
11337 
11338       /* handle pointer sRefs, record fields, arrays, etc... */
11339 
11340       if (!ctype_isRealSU (t1))
11341 	{
11342 	  DPRINTF (("Copying real! %s", ctype_unparse (t1)));
11343 	  sRef_copyRealDerivedComplete (s1, s2);
11344 	}
11345       else
11346 	{
11347 	  /*
11348 	  ** Fields should alias
11349 	  */
11350 
11351 	  DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
11352 	}
11353 
11354       if (ctype_isMutable (t1) && sRef_isKnown (s1))
11355 	{
11356 	  usymtab_clearAlias (s1);
11357 	  usymtab_addMustAlias (s1, s2);
11358 	  DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
11359 	}
11360       else
11361 	{
11362 	  DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11363 	}
11364 
11365       if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11366 	{
11367 	  usymtab_unguard (s1);
11368 	}
11369     }
11370 }
11371 
exprNode_updateLocation(exprNode e,fileloc loc)11372 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11373 {
11374   if (exprNode_isDefined (e))
11375     {
11376       e->loc = fileloc_update (e->loc, loc);
11377     }
11378   else
11379     {
11380       e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11381     }
11382 
11383   return (e);
11384 }
11385 
checkUniqueParams(exprNode fcn,exprNode current,exprNodeList args,int paramno,uentry ucurrent)11386 static void checkUniqueParams (exprNode fcn,
11387 			       /*@notnull@*/ exprNode current,
11388 			       exprNodeList args,
11389 			       int paramno, uentry ucurrent)
11390 {
11391   int iparamno = 0;
11392   sRef thisref = exprNode_getSref (current);
11393 
11394   /*
11395   ** Check if any argument could match this argument.
11396   */
11397 
11398   exprNodeList_elements (args, icurrent)
11399     {
11400       iparamno++;
11401 
11402       if (iparamno != paramno)
11403 	{
11404 	  sRef sr = exprNode_getSref (icurrent);
11405 
11406 	  if (sRef_similarRelaxed (thisref, sr))
11407 	    {
11408 	      if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11409 		{
11410 		  voptgenerror
11411 		    (FLG_ALIASUNIQUE,
11412 		     message
11413 		     ("Parameter %d (%s) to function %s is declared %s but "
11414 		      "is aliased by parameter %d (%s)",
11415 		      paramno,
11416 		      exprNode_unparse (current),
11417 		      exprNode_unparse (fcn),
11418 		      alkind_unparse (uentry_getAliasKind (ucurrent)),
11419 		      iparamno, exprNode_unparse (icurrent)),
11420 		     current->loc);
11421 		}
11422 	    }
11423 	  else
11424 	    {
11425 	      sRefSet aliases = usymtab_canAlias (sr);
11426 
11427 	      sRefSet_allElements (aliases, asr)
11428 		{
11429 		  if (ctype_isUnknown (sRef_getType (thisref)))
11430 		    {
11431 		      sRef_setType (thisref, uentry_getType (ucurrent));
11432 		    }
11433 
11434 		  if (sRef_similarRelaxed (thisref, asr))
11435 		    {
11436 		      if (sRef_isExternal (asr))
11437 			{
11438 			  if (sRef_isLocalState (thisref))
11439 			    {
11440 			      ; /* okay */
11441 			    }
11442 			  else
11443 			    {
11444 			      sRef base = sRef_getRootBase (asr);
11445 
11446 			      if (!sRef_similar (sRef_getBase (asr), thisref))
11447 				{
11448 				  if (sRef_isUnique (base) || sRef_isOnly (base)
11449 				      || sRef_isKept (base)
11450 				      || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11451 				      || (sRef_isAddress (thisref)
11452 					  && sRef_isLocalVar (sRef_getRootBase (thisref))))
11453 				    {
11454 				      ; /* okay, no error */
11455 				    }
11456 				  else
11457 				    {
11458 				      voptgenerror
11459 					(FLG_MAYALIASUNIQUE,
11460 					 message
11461 					 ("Parameter %d (%s) to function %s is declared %s but "
11462 					  "may be aliased externally by parameter %d (%s)",
11463 					  paramno,
11464 					  exprNode_unparse (current),
11465 					  exprNode_unparse (fcn),
11466 					  alkind_unparse (uentry_getAliasKind (ucurrent)),
11467 					  iparamno, exprNode_unparse (icurrent)),
11468 					 current->loc);
11469 				    }
11470 				}
11471 			    }
11472 			}
11473 		      else
11474 			{
11475 			  voptgenerror
11476 			    (FLG_ALIASUNIQUE,
11477 			     message
11478 			     ("Parameter %d (%s) to function %s is declared %s but "
11479 			      "is aliased externally by parameter %d (%s) through "
11480 			      "alias %q",
11481 			      paramno,
11482 			      exprNode_unparse (current),
11483 			      exprNode_unparse (fcn),
11484 			      alkind_unparse (uentry_getAliasKind (ucurrent)),
11485 			      iparamno, exprNode_unparse (icurrent),
11486 			      sRef_unparse (asr)),
11487 			     current->loc);
11488 			}
11489 		    }
11490 		} end_sRefSet_allElements;
11491 	      sRefSet_free (aliases);
11492 	    }
11493 	}
11494     } end_exprNodeList_elements;
11495 }
11496 
exprNode_getLongValue(exprNode e)11497 long exprNode_getLongValue (exprNode e)
11498 {
11499   long value;
11500 
11501   if (exprNode_hasValue (e) && multiVal_isInt (exprNode_getValue (e)))
11502     {
11503       value = multiVal_forceInt (exprNode_getValue (e));
11504     }
11505   else
11506     {
11507       value = 0; /* Unknown value */
11508     }
11509 
11510   return value;
11511 }
11512 
exprNode_getNextSequencePoint(exprNode e)11513 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11514 {
11515   /*
11516   ** Returns the location of the sequence point following e.
11517   **
11518   ** Only works for statements (for now).
11519   */
11520 
11521   if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11522     lltok t = exprData_getUopTok (e->edata);
11523     return fileloc_copy(lltok_getLoc (t));
11524   } else {
11525     /* drl possible problem : warning fix
11526        llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11527     */
11528     return fileloc_undefined;
11529   }
11530  }
11531 
exprNode_createNew(ctype c)11532 exprNode exprNode_createNew(ctype c)
11533 {
11534   exprNode ret;
11535 
11536   ret = exprNode_createPlain (c);
11537 
11538   return ret;
11539 }
11540 
exprNode_isInitBlock(exprNode e)11541 bool exprNode_isInitBlock (exprNode e)
11542 {
11543   return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);
11544 }
11545 
11546 /*drl 3/2/2003 moved this function out of constraint.c */
exprNode_copyConstraints(exprNode dst,exprNode src)11547 exprNode exprNode_copyConstraints (/*@returned@*/ exprNode dst, exprNode src)
11548 {
11549 
11550   llassert (exprNode_isDefined (dst) );
11551   llassert (exprNode_isDefined (src) );
11552 
11553   constraintList_free (dst->ensuresConstraints);
11554   constraintList_free (dst->requiresConstraints);
11555   constraintList_free (dst->trueEnsuresConstraints);
11556   constraintList_free (dst->falseEnsuresConstraints);
11557 
11558   dst->ensuresConstraints = constraintList_copy (src->ensuresConstraints);
11559   dst->requiresConstraints = constraintList_copy (src->requiresConstraints);
11560   dst->trueEnsuresConstraints = constraintList_copy (src->trueEnsuresConstraints);
11561   dst->falseEnsuresConstraints = constraintList_copy (src->falseEnsuresConstraints);
11562   return dst;
11563 }
11564 
exprNode_revealState(exprNode e)11565 void exprNode_revealState (exprNode e)
11566 {
11567   if (exprNode_isDefined (e)) {
11568     llmsg (message ("%s: State of %s: %s", fileloc_unparse (exprNode_loc (e)),
11569 		    exprNode_unparse (e), sRef_unparseFull (e->sref)));
11570   } else {
11571     llmsg (message ("%s: Reveal state undefined", fileloc_unparse (g_currentloc)));
11572   }
11573 }
11574