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