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