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