]> andersk Git - splint.git/blob - src/exprNode.c
a55acda5c23a3323e059b25ef3a321e09f24d911
[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
1061       int nelements = long_toInt (ctype_getArraySize (t1));
1062       
1063       llassert (multiVal_isString (mval));
1064       slit = multiVal_forceString (mval);
1065       
1066       len = cstring_lengthExpandEscapes (slit);
1067       
1068       
1069       if (len == nelements)
1070         {
1071           mstring temp;
1072
1073           temp = cstring_expandEscapes(slit);
1074
1075           if (temp[len-1] == '\0')
1076             {
1077               voptgenerror 
1078                 (FLG_STRINGLITNOROOMFINALNULL,
1079                  message ("String literal with %d character%& "
1080                           "is assigned to %s (no room for final null terminator): %s",
1081                           len + 1,
1082                           ctype_unparse (t1),
1083                           exprNode_unparse (e2)),
1084                  e2->loc);
1085             }
1086           else
1087             {
1088           
1089           
1090           voptgenerror 
1091             (FLG_STRINGLITNOROOM,
1092              message ("String literal with %d character%& "
1093                       "is assigned to %s (no room for null terminator): %s",
1094                       len + 1,
1095                       ctype_unparse (t1),
1096                       exprNode_unparse (e2)),
1097              e2->loc);
1098             }
1099         }
1100       else if (len > nelements) 
1101         {
1102           voptgenerror 
1103             (FLG_STRINGLITTOOLONG,
1104              message ("String literal with %d character%& (counting null terminator) "
1105                       "is assigned to %s (insufficient storage available): %s",
1106                       len + 1,
1107                       ctype_unparse (t1),
1108                       exprNode_unparse (e2)),
1109              e2->loc);                        
1110         }
1111       else if (len < nelements - 1)
1112         {
1113           voptgenerror 
1114             (FLG_STRINGLITSMALLER,
1115              message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1116                       len + 1,
1117                       ctype_unparse (t1),
1118                       exprNode_unparse (e2)),
1119              e2->loc);    
1120         }
1121       else
1122         {
1123           ; /* okay */
1124         }
1125     }
1126 }
1127
1128 static /*@only@*/ /*@notnull@*/ exprNode
1129 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1130 {
1131   exprNode e = exprNode_createId (c);
1132   sRef sr = e->sref;
1133
1134   uentry_setUsed (c, e->loc);
1135
1136   if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1137     {
1138       checkGlobUse (c, FALSE, e);
1139     }
1140
1141   return (e);
1142 }
1143
1144 static bool
1145 exprNode_isZero (exprNode e)
1146 {
1147   if (exprNode_isDefined (e))
1148     {
1149       multiVal m = exprNode_getValue (e);
1150       
1151       if (multiVal_isInt (m))
1152         {
1153           return (multiVal_forceInt (m) == 0);
1154         }
1155     }
1156
1157   return FALSE;
1158 }
1159
1160 static bool
1161 exprNode_isNonNegative (exprNode e)
1162 {
1163   if (exprNode_isDefined (e))
1164     {
1165       multiVal m = exprNode_getValue (e);
1166       
1167       if (multiVal_isInt (m))
1168         {
1169           return (multiVal_forceInt (m) >= 0);
1170         }
1171
1172       /*
1173       ** This is not always true if programmer defines enum
1174       ** values, but then the constant should be known.
1175       */
1176
1177       if (ctype_isEnum (ctype_realType (e->typ)))
1178         {
1179           return TRUE;
1180         }
1181     }
1182
1183   return FALSE;
1184 }
1185
1186 /*
1187 ** a[x]  - uses a but NOT a[] 
1188 **         result sref = a[]  (set/use in assignment)
1189 ** 
1190 ** The syntax x[a] is also legal in C, and has the same 
1191 ** semantics.  If ind is an array, and arr is an int, flip
1192 ** the arguments.
1193 */
1194
1195 /*@only@*/ exprNode
1196 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1197 {
1198   /*
1199   ** error in arr, error propagates (no new messages)
1200   ** error in ind, assume valid and continue
1201   */
1202
1203   DPRINTF (("Array fetch: %s / %s",
1204             exprNode_unparse (e1), exprNode_unparse (e2)));
1205
1206   if (exprNode_isError (e1))
1207     {
1208       exprNode_free (e2);
1209       return (exprNode_makeError ());
1210     }
1211   else
1212     {
1213       exprNode arr;
1214       exprNode ind;
1215       ctype carr = exprNode_getType (e1);
1216       ctype crarr = ctype_realType (carr);
1217  
1218       /*
1219       ** this sets up funny aliasing, that leads to spurious
1220       ** splint errors.  Hence, the i2 comments.
1221       */
1222
1223       /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1224       if (ctype_isKnown (crarr)
1225           && !ctype_isRealArray (crarr) 
1226           && ctype_isRealNumeric (crarr) 
1227           && !exprNode_isError (e2)
1228           && ctype_isRealAP (exprNode_getType (e2)))  /* fetch like 3[a] */
1229         {
1230           arr = e2;
1231           ind = e1;
1232
1233           carr = exprNode_getType (arr);
1234           crarr = ctype_realType (carr);
1235         }
1236       else
1237         {
1238           arr = e1;
1239           ind = e2;
1240         }
1241
1242       DPRINTF (("arr: %s", exprNode_unparse (arr)));
1243
1244       if (sRef_possiblyNull (arr->sref))
1245         {
1246           if (!usymtab_isGuarded (arr->sref))
1247             {
1248               if (optgenerror (FLG_NULLDEREF,
1249                                message ("Index of %s pointer %q: %s", 
1250                                         sRef_nullMessage (arr->sref),
1251                                         sRef_unparse (arr->sref),
1252                                         exprNode_unparse (arr)),
1253                                arr->loc))
1254                 {
1255                   DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1256                   sRef_showNullInfo (arr->sref);
1257
1258                   /* suppress future messages */
1259                   sRef_setNullError (arr->sref); 
1260                 }
1261             }
1262         }
1263
1264       if (exprNode_isError (ind))
1265         {
1266           if ((ctype_isArrayPtr (crarr) 
1267                && !ctype_isFunction (crarr))
1268               || ctype_isUnknown (carr))
1269             {
1270               exprNode ret = exprNode_createPartialCopy (arr);
1271
1272               if (ctype_isKnown (carr))
1273                 {
1274                   ret->typ = ctype_baseArrayPtr (crarr);
1275                 }
1276               else
1277                 {
1278                   ret->typ = ctype_unknown;
1279                 }
1280               
1281               ret->sref = sRef_makeArrayFetch (arr->sref);
1282               
1283               ret->kind = XPR_FETCH;
1284
1285               /*
1286               ** Because of funny aliasing (when arr and ind are
1287               ** flipped) spurious errors would be reported here.
1288               */
1289          
1290               /*@i2@*/ ret->edata = exprData_makePair (arr, ind);             
1291               checkSafeUse (ret, arr->sref);
1292               return (ret);
1293             }
1294           else
1295             {
1296               voptgenerror (FLG_TYPE,
1297                             message ("Array fetch from non-array (%t): %s[%s]", carr, 
1298                                      exprNode_unparse (e1), exprNode_unparse (e2)),
1299                             arr->loc);
1300               exprNode_free (arr);
1301               return (exprNode_makeError ());
1302             }
1303         }
1304       else
1305         {
1306           if (!ctype_isForceRealInt (&(ind->typ)))
1307             {
1308               ctype rt = ctype_realType (ind->typ);
1309
1310               if (ctype_isChar (rt))
1311                 {
1312                   vnoptgenerror
1313                     (FLG_CHARINDEX,
1314                      message ("Array fetch using non-integer, %t: %s[%s]",
1315                               ind->typ, 
1316                               exprNode_unparse (e1), exprNode_unparse (e2)),
1317                      arr->loc);
1318                 }
1319               else if (ctype_isEnum (rt))
1320                 {
1321                   vnoptgenerror
1322                     (FLG_ENUMINDEX,
1323                      message ("Array fetch using non-integer, %t: %s[%s]",
1324                               ind->typ, 
1325                               exprNode_unparse (e1), exprNode_unparse (e2)),
1326                      arr->loc);
1327                 }
1328               else
1329                 {
1330                   voptgenerror 
1331                     (FLG_TYPE,
1332                      message ("Array fetch using non-integer, %t: %s[%s]",
1333                               ind->typ, 
1334                               exprNode_unparse (e1), exprNode_unparse (e2)),
1335                      arr->loc);
1336                 }
1337
1338               multiVal_free (ind->val);
1339               ind->val = multiVal_unknown ();
1340             }
1341           
1342           if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1343             {
1344               exprNode ret = exprNode_createSemiCopy (arr);
1345               multiVal m = exprNode_getValue (ind);
1346               
1347               ret->typ = ctype_baseArrayPtr (crarr);
1348               ret->kind = XPR_FETCH;
1349               
1350               if (multiVal_isInt (m))
1351                 {
1352                   int i = (int) multiVal_forceInt (m);
1353                   
1354                   if (sRef_isValid (arr->sref)) {
1355                     ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1356                   } else {
1357                     ret->sref = sRef_undefined;
1358                   }
1359                 }
1360               else
1361                 {
1362                   ret->sref = sRef_makeArrayFetch (arr->sref);
1363                 }
1364               
1365               ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1366               ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1367               ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1368               
1369               /* (see comment on spurious errors above) */
1370               /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1371               
1372               exprNode_checkUse (ret, ind->sref, ind->loc);
1373               exprNode_checkUse (ret, arr->sref, arr->loc);
1374               
1375               return (ret);
1376             }
1377           else
1378             {
1379               if (ctype_isUnknown (carr))
1380                 {
1381                   exprNode ret = exprNode_createPartialCopy (arr);
1382                   
1383                   ret->kind = XPR_FETCH;
1384                   ret->typ = ctype_unknown;
1385                   ret->sets = sRefSet_union (ret->sets, ind->sets);
1386                   ret->msets = sRefSet_union (ret->msets, ind->msets);
1387                   ret->uses = sRefSet_union (ret->uses, ind->uses);
1388
1389                   /* (see comment on spurious errors above) */            
1390                   /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1391                   
1392                   exprNode_checkUse (ret, ind->sref, ind->loc);
1393                   exprNode_checkUse (ret, arr->sref, arr->loc);
1394                   return (ret);
1395                 }
1396               else
1397                 {
1398                   voptgenerror
1399                     (FLG_TYPE,
1400                      message ("Array fetch from non-array (%t): %s[%s]", carr, 
1401                               exprNode_unparse (e1), exprNode_unparse (e2)),
1402                      arr->loc);
1403
1404                   exprNode_free (arr);
1405                   exprNode_free (ind);
1406
1407                   return (exprNode_makeError ());
1408                 }
1409             }
1410         }
1411     }
1412   BADEXIT;
1413 }
1414
1415
1416 static int
1417 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t, 
1418            exprNodeList args, exprNode ret)
1419 {
1420   return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1421 }
1422
1423 /*
1424 ** checkPrintfArgs --- checks arguments for printf-like functions
1425 **    Arguments before ... have already been checked.
1426 **    The argument before the ... is a char *.  
1427 **    argno is the format string argument.
1428 */
1429
1430 static void
1431 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn, 
1432                  exprNodeList args, exprNode ret, int argno)
1433 {
1434   /*
1435   ** the last argument before the elips is the format string 
1436   */
1437
1438   int i = argno;
1439   fileloc formatloc;
1440   int nargs = exprNodeList_size (args);
1441   uentryList params = uentry_getParams (fcn);
1442   exprNode a; 
1443
1444   /*
1445   ** These should be ensured by checkSpecialFunction
1446   */
1447
1448   llassert (uentryList_size (params) == argno + 1);
1449   llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1450
1451   a = exprNodeList_getN (args, argno - 1);
1452   formatloc = fileloc_copy (exprNode_loc (a));
1453
1454   if (exprNode_isDefined (a) && exprNode_isStringLiteral (a) 
1455       && exprNode_knownStringValue (a))
1456     {
1457       char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1458       char *code = format;
1459       char *ocode = code;
1460
1461       nargs = exprNodeList_size (args);
1462
1463       while ((code = strchr (code, '%')) != NULL)
1464         {
1465           char *origcode = code;
1466           cstring codetext = cstring_newEmpty ();
1467           char key = *(++code);                 
1468           ctype modtype = ctype_int;
1469           bool modified = FALSE;
1470
1471           fileloc_addColumn (formatloc, code - ocode);
1472
1473           codetext = cstring_appendChar (codetext, key);
1474
1475           /* ignore flags */
1476           while (isFlagKey (key)) 
1477             {
1478               key = *(++code);
1479               codetext = cstring_appendChar (codetext, key);
1480               fileloc_incColumn (formatloc);
1481             }
1482
1483           if (key == 'm') /* skipped in syslog */
1484             {
1485               continue; 
1486             }
1487           
1488           /* ignore field width */
1489           while (isdigit ((int) key) != 0) 
1490             {
1491               key = *(++code);
1492               codetext = cstring_appendChar (codetext, key);
1493               fileloc_incColumn (formatloc);
1494             }
1495           
1496           /* ignore precision */
1497           if (key == '.')
1498             {
1499               key = *(++code);
1500               codetext = cstring_appendChar (codetext, key);
1501               fileloc_incColumn (formatloc);
1502
1503               /*
1504               ** In printf, '*' means: read the next arg as an int for the
1505               ** field width.  This seems to be missing from my copy of the 
1506               ** standard x3.159-1989.  Setion 4.9.6.1 refers to * (described
1507               ** later) but never does.
1508               */
1509               
1510               if (key == '*') 
1511                 {
1512                   ; /* don't do anything --- handle later */
1513                 }
1514               else
1515                 {
1516                   while (isdigit ((int) key) != 0)
1517                     {
1518                       key = *(++code);
1519                       codetext = cstring_appendChar (codetext, key);
1520                       fileloc_incColumn (formatloc);
1521                     }
1522                 }
1523             }
1524
1525           if (key == 'h')
1526             {
1527               modtype = ctype_sint;  /* short */
1528               key = *(++code);
1529               codetext = cstring_appendChar (codetext, key);
1530               fileloc_incColumn (formatloc);
1531             }
1532           else if (key == 'l' || key == 'L') 
1533             {
1534               modtype = ctype_lint; /* long */
1535               key = *(++code);
1536               codetext = cstring_appendChar (codetext, key);
1537               fileloc_incColumn (formatloc);
1538
1539               if (key == 'l' || key == 'L') { 
1540                 modtype = ctype_llint; /* long long */
1541                 key = *(++code);
1542                 codetext = cstring_appendChar (codetext, key);
1543                 fileloc_incColumn (formatloc);
1544               }
1545             }
1546           else
1547             {
1548               ; /* no modifier */
1549             }
1550           
1551           /* now, key = type of conversion to apply */
1552           ++code;
1553           fileloc_incColumn (formatloc);
1554
1555           if (key != '%') 
1556             {
1557               if (i >= nargs)
1558                 {
1559                   if (optgenerror 
1560                       (FLG_TYPE,
1561                        message ("No argument corresponding to %q format "
1562                                 "code %d (%%%s): \"%s\"",
1563                                 uentry_getName (fcn),
1564                                 i, codetext,
1565                                 cstring_fromChars (format)),
1566                        f->loc))
1567                     {
1568                       if (fileloc_isDefined (formatloc)
1569                           && context_getFlag (FLG_SHOWCOL))
1570                         {
1571                           llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1572                                           formatloc);
1573                         }
1574                     }
1575                   i++;
1576                 }
1577               else
1578                 {
1579                   a = exprNodeList_getN (args, i);
1580                   i++;
1581                   
1582                   if (!exprNode_isError (a))
1583                     {
1584                       ctype expecttype;
1585
1586                       switch (key)
1587                         {
1588                         case '*': /* int argument for fieldwidth */
1589                           expecttype = ctype_int;
1590                           *(--code) = '%'; /* convert it for next code */
1591                           fileloc_subColumn (formatloc, 1);
1592                           /*@switchbreak@*/ break;              
1593                         case 'u':
1594                         case 'o':
1595                           expecttype = ctype_combine (ctype_uint, modtype);
1596                           /*@switchbreak@*/ break;
1597                           
1598                         case 'i': /* int argument */ 
1599                         case 'd':
1600                           expecttype = ctype_combine (ctype_int, modtype);
1601                           /*@switchbreak@*/ break;
1602
1603                         case 'x': /* unsigned int */ 
1604                         case 'X':
1605                           expecttype = ctype_combine (ctype_uint, modtype); 
1606
1607                           /*@switchbreak@*/ break;
1608                           
1609                         case 'e':
1610                         case 'E':
1611                         case 'g':
1612                         case 'G':
1613                         case 'f': /* double */
1614                           expecttype = ctype_combine (ctype_double, modtype);
1615                           /*@switchbreak@*/ break;
1616                           
1617                         case 'c': /* int converted to char (check its a char?) */
1618                           expecttype = ctype_makeConj (ctype_int, 
1619                                                        ctype_makeConj (ctype_char,
1620                                                                        ctype_uchar));
1621                           /*@i231@*/
1622                           /* evans 2001-10-05 - changed to reflect correct ISO spec:
1623                              int converted to char */
1624                           
1625                           /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
1626                           /*@switchbreak@*/ break;
1627                               
1628                         case 's': /* string */
1629                           expecttype = ctype_string;
1630                           /*@switchbreak@*/ break;
1631                         case '[': 
1632                           /* skip to ']' */
1633                           while (((key = *(++code)) != ']') 
1634                                  && (key != '\0'))
1635                             {
1636                               codetext = cstring_appendChar (codetext, key);
1637                               fileloc_incColumn (formatloc);
1638                             }
1639                           
1640                           if (key == '\0')
1641                             {
1642                               llfatalerrorLoc
1643                                 (message ("Bad character set format: %s", 
1644                                           cstring_fromChars (origcode)));
1645                             }
1646                           
1647                           expecttype = ctype_string;
1648                           /*@switchbreak@*/ break;
1649                           
1650                         case 'p': /* pointer */
1651                           expecttype = ctype_makePointer (ctype_void);
1652                           uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1653                           sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
1654                           /*@switchbreak@*/ break;
1655                           
1656                         case 'n': /* pointer to int, modified by call! */
1657                           expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1658                           modified = TRUE;
1659                           uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1660                           /*@switchbreak@*/ break;
1661
1662                         case 'm': /* in a syslog, it doesn't consume an argument */
1663                           /* should check we're really doing syslog */
1664                           
1665                           /*@switchbreak@*/ break;
1666
1667                           
1668                         default:
1669                           expecttype = ctype_unknown;
1670                           
1671                           voptgenerror
1672                             (FLG_FORMATCODE,
1673                              message ("Unrecognized format code: %s", 
1674                                       cstring_fromChars (origcode)),
1675                              fileloc_isDefined (formatloc) 
1676                              ? formatloc : g_currentloc);
1677
1678                           /*@switchbreak@*/ break;
1679                         }
1680
1681                       if (!(exprNode_matchArgType (expecttype, a)))
1682                         {
1683                           if (ctype_isVoidPointer (expecttype) 
1684                               && ctype_isRealAbstract (a->typ)
1685                               && (context_getFlag (FLG_ABSTVOIDP)))
1686                             {
1687                               ;
1688                             }
1689                           else
1690                             {
1691                               if (llgenformattypeerror 
1692                                   (expecttype, exprNode_undefined,
1693                                    a->typ, a,
1694                                    message ("Format argument %d to %q (%%%s) expects "
1695                                             "%t gets %t: %s",
1696                                             i - argno,
1697                                             uentry_getName (fcn), 
1698                                             codetext,
1699                                             expecttype,
1700                                             a->typ, exprNode_unparse (a)),
1701                                    a->loc))
1702                                 {
1703                                   if (fileloc_isDefined (formatloc)
1704                                       && context_getFlag (FLG_SHOWCOL))
1705                                     {
1706                                       llgenindentmsg
1707                                         (cstring_makeLiteral 
1708                                          ("Corresponding format code"),
1709                                          formatloc);
1710                                     }
1711                                 }
1712                             }
1713                         }
1714
1715                       uentry_setType (regArg, expecttype);
1716                       checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1717                       
1718                       if (ctype_equal (expecttype, ctype_string))
1719                         {
1720                           exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1721                         }
1722                       
1723                       uentry_setType (regArg, ctype_unknown);
1724                       uentry_fixupSref (regArg);
1725                       
1726                       if (modified)
1727                         {
1728                           exprNode_checkCallModifyVal (a->sref, args, f, ret);
1729                         }
1730                     }
1731                   else
1732                     {
1733                       ;
1734                     }
1735                 }
1736             }
1737
1738           ocode = code;
1739           cstring_free (codetext);
1740         }
1741   
1742       if (i < nargs)
1743         {
1744           voptgenerror (FLG_TYPE,
1745                         message ("Format string for %q has %d arg%&, given %d", 
1746                                  uentry_getName (fcn), i - argno, nargs - argno),
1747                         f->loc);
1748         }
1749     }
1750   else
1751     {
1752       /* no checking possible for compile-time unknown format strings */
1753       if (exprNode_isDefined (a))
1754         {
1755           voptgenerror
1756             (FLG_FORMATCONST,
1757              message ("Format string parameter to %s is not a compile-time constant: %s",
1758                       exprNode_unparse (f),
1759                       exprNode_unparse (a)),
1760              f->loc);
1761         }
1762     }
1763   
1764   fileloc_free (formatloc);
1765 }
1766
1767 static void
1768 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn, 
1769                  exprNodeList args, exprNode ret, int argno)
1770 {
1771   int i = argno;
1772   fileloc formatloc;
1773   int nargs = exprNodeList_size (args);
1774   uentryList params = uentry_getParams (fcn);
1775   exprNode a; 
1776
1777   /*
1778   ** These should be ensured by checkSpecialFunction
1779   */
1780
1781   llassert (uentryList_size (params) == argno + 1);
1782   llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1783
1784   a = exprNodeList_getN (args, argno - 1);
1785   formatloc = fileloc_copy (exprNode_loc (a));
1786
1787   if (exprNode_isDefined (a) && exprNode_isStringLiteral (a) 
1788       && exprNode_knownStringValue (a))
1789     {
1790       char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1791       char *code = format;
1792       char *ocode = code;
1793
1794       nargs = exprNodeList_size (args);
1795
1796       while ((code = strchr (code, '%')) != NULL)
1797         {
1798           char *origcode = code;
1799           char key = *(++code);                 
1800           cstring codetext = cstring_newEmpty ();
1801           ctype modtype = ctype_int;
1802           char modifier = '\0';
1803           bool modified = TRUE;
1804           bool ignore = FALSE;
1805
1806           codetext = cstring_appendChar (codetext, key);
1807           fileloc_addColumn (formatloc, code - ocode);
1808
1809           /*
1810           ** this is based on ANSI standard library description of fscanf
1811           ** (from ANSI standard X3.159-1989, 4.9.6.1)
1812           */
1813               
1814           /* '*' suppresses assignment (does not need match argument) */
1815           
1816           if (key == '*') 
1817             {
1818               key = *(++code);
1819               codetext = cstring_appendChar (codetext, key);
1820               modified = FALSE; 
1821               ignore = TRUE;
1822               fileloc_incColumn (formatloc);
1823             }
1824           
1825           /* ignore field width */
1826           while (isdigit ((int) key) != 0)
1827             {
1828               key = *(++code);
1829               codetext = cstring_appendChar (codetext, key);
1830               fileloc_incColumn (formatloc);
1831             }
1832           
1833           if (key == 'h')
1834             {
1835               modtype = ctype_sint;  /* short */
1836               key = *(++code);
1837               codetext = cstring_appendChar (codetext, key);
1838               fileloc_incColumn (formatloc);
1839             }
1840           else if (key == 'l' || key == 'L') 
1841             {
1842               modtype = ctype_lint; /* long */
1843               modifier = key;
1844
1845               key = *(++code);
1846               codetext = cstring_appendChar (codetext, key);
1847
1848               fileloc_incColumn (formatloc);
1849
1850               if (key == 'l' || key == 'L') { 
1851                 modtype = ctype_llint; /* long long */
1852                 key = *(++code);
1853                 codetext = cstring_appendChar (codetext, key);
1854                 fileloc_incColumn (formatloc);
1855               }
1856             }
1857           else
1858             {
1859               ; /* no modifier */
1860             }
1861           
1862           /* now, key = type of conversion to apply */
1863           ++code;
1864           fileloc_incColumn (formatloc);
1865
1866           if (key != '%') 
1867             {
1868               if (ignore)
1869                 {
1870                   ;
1871                 }
1872               else
1873                 {
1874                   if (i >= nargs)
1875                     {
1876                       if (optgenerror 
1877                           (FLG_TYPE,
1878                            message ("No argument corresponding to %q format "
1879                                     "code %d (%%%s): \"%s\"",
1880                                     uentry_getName (fcn),
1881                                     i, codetext,
1882                                     cstring_fromChars (format)),
1883                            f->loc))
1884                         {
1885                           if (fileloc_isDefined (formatloc)
1886                               && context_getFlag (FLG_SHOWCOL))
1887                             {
1888                               llgenindentmsg
1889                                 (cstring_makeLiteral ("Corresponding format code"),
1890                                  formatloc);
1891                             }
1892                         }
1893                       i++;
1894                     }
1895                   else
1896                     {
1897                       a = exprNodeList_getN (args, i);
1898                       i++;
1899                   
1900                       if (!exprNode_isError (a))
1901                         {
1902                           ctype expecttype;
1903
1904                           switch (key)
1905                             {
1906                             case '*': /* int argument for fieldwidth */
1907                               expecttype = ctype_makePointer (ctype_int);
1908                               *(--code) = '%'; /* convert it for next code */
1909                               fileloc_subColumn (formatloc, 1);
1910                               /*@switchbreak@*/ break;          
1911                             case 'u':
1912                             case 'o':
1913                               expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1914                               /*@switchbreak@*/ break;
1915                               
1916                             case 'i': 
1917                             case 'd':
1918                             case 'x':
1919                             case 'X': /* unsigned int */
1920                               expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1921                               /*@switchbreak@*/ break;
1922                               
1923                             case 'e':
1924                             case 'E':
1925                             case 'g':
1926                             case 'G':
1927                             case 'f': 
1928                               /* printf is double, scanf is float! */
1929
1930                               if (modifier == 'l') 
1931                                 {
1932                                   expecttype = ctype_makePointer (ctype_double);
1933                                 }
1934                               else if (modifier == 'L')
1935                                 {
1936                                   expecttype = ctype_makePointer (ctype_ldouble);
1937                                 }
1938                               else 
1939                                 {
1940                                   llassert (modifier == '\0');
1941                                   expecttype = ctype_makePointer (ctype_float);
1942                                 }
1943                               /*@switchbreak@*/ break;
1944                               
1945                             case 'c': /* int converted to char (check its a char?) */
1946                               expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1947                               /*@switchbreak@*/ break;
1948                               
1949                             case 's': /* string */
1950                               expecttype = ctype_string;
1951                               /*@switchbreak@*/ break;
1952
1953                             case '[': 
1954                               /* skip to ']' */
1955                               while (((key = *(++code)) != ']') 
1956                                      && (key != '\0'))
1957                                 {
1958                                   codetext = cstring_appendChar (codetext, key);
1959                                   fileloc_incColumn (formatloc);
1960                                 }
1961                               
1962                               if (key == '\0')
1963                                 {
1964                                   llfatalerrorLoc
1965                                     (message ("Bad character set format: %s", 
1966                                               cstring_fromChars (origcode)));
1967                                 }
1968                               
1969                               expecttype = ctype_string;
1970                               /*@switchbreak@*/ break;
1971
1972                               
1973                             case 'p': /* pointer */
1974                               voptgenerror
1975                                 (FLG_FORMATCODE,
1976                                  message ("Format code should not be used in scanf: %s", 
1977                                           cstring_fromChars (origcode)),
1978                                  fileloc_isDefined (formatloc) 
1979                                  ? formatloc : g_currentloc);
1980                               
1981                               expecttype = ctype_unknown;
1982                               /*@switchbreak@*/ break;
1983                               
1984                             case 'n': /* pointer to int, modified by call! */
1985                               expecttype = ctype_makePointer (ctype_int);
1986                               /*@switchbreak@*/ break;
1987                           
1988                             default:
1989                               expecttype = ctype_unknown;
1990                               
1991                               voptgenerror
1992                                 (FLG_FORMATCODE,
1993                                  message ("Unrecognized format code: %s", 
1994                                           cstring_fromChars (origcode)),
1995                                  fileloc_isDefined (formatloc) 
1996                                  ? formatloc : g_currentloc);
1997                               
1998                               /*@switchbreak@*/ break;
1999                             }
2000                           
2001                           if (!(exprNode_matchArgType (expecttype, a)))
2002                             {
2003                               if (ctype_isVoidPointer (expecttype) 
2004                                   && ctype_isRealAbstract (a->typ)
2005                                   && (context_getFlag (FLG_ABSTVOIDP)))
2006                                 {
2007                                   ;
2008                                 }
2009                               else
2010                                 {
2011                                   if (llgenformattypeerror 
2012                                       (expecttype, exprNode_undefined,
2013                                        a->typ, a,
2014                                        message ("Format argument %d to %q (%%%s) expects "
2015                                                 "%t gets %t: %s",
2016                                                 i - argno,
2017                                                 uentry_getName (fcn), 
2018                                                 codetext, expecttype,
2019                                                 a->typ, exprNode_unparse (a)),
2020                                        a->loc))
2021                                     {
2022                                       if (fileloc_isDefined (formatloc)
2023                                           && context_getFlag (FLG_SHOWCOL))
2024                                         {
2025                                           llgenindentmsg
2026                                             (cstring_makeLiteral 
2027                                              ("Corresponding format code"),
2028                                              formatloc);
2029                                         }
2030                                     }
2031                                 }
2032                             }
2033                           
2034                           uentry_setType (outArg, expecttype);
2035                           checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2036                           uentry_setType (outArg, ctype_unknown);
2037                           uentry_fixupSref (outArg);
2038                           
2039                           if (modified)
2040                             {
2041                               exprNode_checkCallModifyVal (a->sref, args, f, ret);
2042                             }
2043                         }
2044                       else
2045                         {
2046                                                   /* a->sref = defref; */
2047                         }
2048                     }
2049                 }
2050             }
2051          
2052           ocode = code;
2053           cstring_free (codetext);
2054         }
2055
2056       if (i < nargs)
2057         {
2058           voptgenerror (FLG_TYPE,
2059                         message ("Format string for %q has %d arg%&, given %d", 
2060                                  uentry_getName (fcn), i - argno, nargs - argno),
2061                         f->loc);
2062         }
2063     }
2064   else
2065     {
2066       /* no checking possible for compile-time unknown format strings */
2067     }
2068
2069   fileloc_free (formatloc);
2070 }
2071                           
2072 static void
2073 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2074                   uentry fcn,
2075                   exprNodeList args,
2076                   /*@unused@*/ int argno)
2077 {
2078   /*
2079   ** the last argument before the elips is the format string 
2080   */
2081
2082   int nargs = exprNodeList_size (args);
2083   int i = argno;
2084   fileloc formatloc;
2085   exprNode a; 
2086
2087   a = exprNodeList_getN (args, argno - 1);
2088   formatloc = fileloc_copy (exprNode_loc (a));
2089
2090   if (ctype_isUnknown (cstringType)) {
2091     if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2092       {
2093         cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2094       }
2095   }
2096  
2097   if (ctype_isUnknown (ctypeType)) {
2098     if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2099       {
2100         ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2101       }
2102   }
2103
2104   if (ctype_isUnknown (filelocType)) {
2105     if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2106       {
2107         filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2108       }
2109   }
2110
2111   if (exprNode_isDefined (a) && exprNode_isStringLiteral (a) 
2112       && exprNode_knownStringValue (a))
2113     {
2114       cstring format = multiVal_forceString (exprNode_getValue (a));
2115       char *code = cstring_toCharsSafe (format);
2116       char *ocode = code;
2117
2118       nargs = exprNodeList_size (args);
2119
2120       while ((code = strchr (code, '%')) != NULL)
2121         {
2122           char *origcode = code;
2123           char key = *(++code);                 
2124           cstring codetext = cstring_newEmpty ();
2125           bool isOnly = FALSE;
2126
2127           codetext = cstring_appendChar (codetext, key);
2128
2129           fileloc_addColumn (formatloc, code - ocode);
2130
2131           while (key >= '0' && key <= '9')
2132             {
2133               key = *(++code);
2134               codetext = cstring_appendChar (codetext, key);
2135               fileloc_incColumn (formatloc);
2136             }
2137           
2138           ++code;
2139           fileloc_incColumn (formatloc);
2140
2141           if (key != '%') 
2142             {
2143               if (key == '&') /* plural marker */
2144                 {
2145                   goto nextKey;
2146                 }
2147
2148               if (i >= nargs)
2149                 {
2150                   voptgenerror
2151                     (FLG_TYPE,
2152                      message ("Message missing format arg %d (%%%s): \"%s\"",
2153                               i + 1, codetext, format), 
2154                      f->loc);
2155                   i++;
2156                 }
2157               else
2158                 {
2159                   a = exprNodeList_getN (args, i);
2160                   i++;
2161                   
2162                 nextKey:
2163                   if (!exprNode_isError (a))
2164                     {
2165                       ctype expecttype;
2166                       
2167                       /*@-loopswitchbreak@*/
2168
2169                       switch (key)
2170                         {
2171                         case 'c':
2172                         case 'h': 
2173                           expecttype = ctype_char; break;
2174                         case 's': 
2175                           expecttype = cstringType; break;
2176                         case 'q': 
2177                           expecttype = cstringType; isOnly = TRUE; break;
2178                         case 'x': 
2179                           expecttype = cstringType; isOnly = TRUE; break;
2180                         case 'd': expecttype = ctype_int; break;
2181                         case 'u': expecttype = ctype_uint; break;
2182                         case 'w': expecttype = ctype_ulint; break;
2183                         case 'f': expecttype = ctype_float; break;
2184                         case 'b': expecttype = ctype_bool; break;
2185                         case 't': expecttype = ctypeType; break;
2186                         case 'l': expecttype = filelocType; break;
2187                         case '&':  /* a wee bit of a hack methinks */
2188                           expecttype = ctype_int;
2189                           break;
2190                         case 'r': expecttype = ctype_bool; break;
2191                         default:  
2192                           expecttype = ctype_unknown;
2193                           voptgenerror
2194                             (FLG_FORMATCODE,
2195                              message ("Unrecognized format code: %s", 
2196                                       cstring_fromChars (origcode)),
2197                              fileloc_isDefined (formatloc) 
2198                              ? formatloc : g_currentloc);
2199                           break;
2200                         }
2201                       /*@=loopswitchbreak@*/
2202
2203                       if (!(exprNode_matchArgType (expecttype, a)))
2204                         {
2205                           if (ctype_isVoidPointer (expecttype) 
2206                               && ctype_isRealAbstract (a->typ)
2207                               && (context_getFlag (FLG_ABSTVOIDP)))
2208                             {
2209                               ;
2210                             }
2211                           else
2212                             {
2213                               if (llgenformattypeerror 
2214                                   (expecttype, exprNode_undefined,
2215                                    a->typ, a,
2216                                    message ("Format argument %d to %q (%%%s) expects "
2217                                             "%t gets %t: %s",
2218                                             i - argno,
2219                                             uentry_getName (fcn), 
2220                                             codetext, expecttype,
2221                                             a->typ, exprNode_unparse (a)),
2222                                    a->loc))
2223                                   {
2224                                   if (fileloc_isDefined (formatloc)
2225                                       && context_getFlag (FLG_SHOWCOL))
2226                                     {
2227                                       llgenindentmsg
2228                                         (cstring_makeLiteral 
2229                                          ("Corresponding format code"),
2230                                          formatloc);
2231                                     }
2232                                 }
2233                             }
2234                         }
2235                       
2236                       if (ctype_equal (expecttype, cstringType))
2237                         {
2238                           if (isOnly)
2239                             {
2240                               checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2241                               uentry_fixupSref (csOnlyArg);
2242                             }
2243                           else
2244                             {
2245                               checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2246                               uentry_fixupSref (csArg);
2247                             }
2248                         }
2249                       else
2250                         {
2251                                                   checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2252                           uentry_fixupSref (regArg);
2253                         }
2254                     }
2255                 }
2256             }
2257
2258           cstring_free (codetext);
2259         }
2260
2261       if (i < nargs)
2262         {
2263           voptgenerror (FLG_TYPE,
2264                         message ("Format string for %q has %d arg%&, given %d", 
2265                                  uentry_getName (fcn), i - argno, nargs -argno),
2266                         f->loc);
2267         }
2268     }
2269   else
2270     {
2271       /* no checking possible for compile-time unknown format strings */
2272     }
2273
2274   fileloc_free (formatloc);
2275 }
2276
2277 static void
2278   checkExpressionDefinedAux (/*@notnull@*/ exprNode e1, 
2279                              /*@notnull@*/ exprNode e2, 
2280                              sRefSet sets1,
2281                              sRefSet sets2, 
2282                              lltok op,
2283                              flagcode flag)
2284 {
2285   bool hadUncon = FALSE;
2286
2287   if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) && 
2288       sRefSet_hasUnconstrained (sets2))
2289     {
2290       voptgenerror
2291         (FLG_EVALORDERUNCON,
2292          message
2293          ("Expression may have undefined behavior (%q used in right operand "
2294           "may set global variable %q used in left operand): %s %s %s", 
2295           sRefSet_unparseUnconstrained (sets2),
2296           sRef_unparse (sRef_getRootBase (e1->sref)),
2297           exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2298          e2->loc);
2299     }
2300
2301   if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) && 
2302       sRefSet_hasUnconstrained (sets1))
2303     {
2304       voptgenerror
2305         (FLG_EVALORDERUNCON,
2306          message
2307          ("Expression has undefined behavior (%q used in left operand "
2308           "may set global variable %q used in right operand): %s %s %s", 
2309           sRefSet_unparseUnconstrained (sets1),
2310           sRef_unparse (e2->sref),
2311           exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2312          e2->loc);
2313     }
2314
2315   sRefSet_realElements (e1->uses, sr)
2316     {
2317       if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2318         {
2319           voptgenerror
2320             (FLG_EVALORDER,
2321              message
2322              ("Expression has undefined behavior (left operand uses %q, "
2323               "modified by right operand): %s %s %s", 
2324               sRef_unparse (sr),
2325               exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2326              e2->loc);
2327         }
2328     } end_sRefSet_realElements;
2329   
2330   sRefSet_realElements (sets1, sr)
2331     {
2332       if (sRef_isMeaningful (sr))
2333         {
2334           if (sRef_same (sr, e2->sref))
2335             {
2336               voptgenerror
2337                 (flag,
2338                  message
2339                  ("Expression has undefined behavior (value of right operand "
2340                   "modified by left operand): %s %s %s", 
2341                   exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2342                  e2->loc);
2343             }
2344           else if (sRefSet_member (e2->uses, sr))
2345             {
2346               voptgenerror
2347                 (flag,
2348                  message 
2349                  ("Expression has undefined behavior (left operand modifies %q, "
2350                   "used by right operand): %s %s %s", 
2351                   sRef_unparse (sr),
2352                   exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2353                  e2->loc);
2354             }
2355           else 
2356             {
2357               if (sRefSet_member (sets2, sr))
2358                 {
2359                   if (sRef_isUnconstrained (sr))
2360                     {
2361                       if (hadUncon)
2362                         {
2363                           ;
2364                         }
2365                       else
2366                         {
2367                           hadUncon = optgenerror
2368                             (FLG_EVALORDERUNCON,
2369                              message 
2370                              ("Expression may have undefined behavior.  Left operand "
2371                               "calls %q; right operand calls %q.  The unconstrained "
2372                               "functions may modify global state used by "
2373                               "the other operand): %s %s %s", 
2374                               sRefSet_unparseUnconstrained (sets1),
2375                               sRefSet_unparseUnconstrained (sets2),
2376                               exprNode_unparse (e1), lltok_unparse (op),
2377                               exprNode_unparse (e2)),
2378                              e2->loc);
2379                         }
2380                     }
2381                   else
2382                     {
2383                       voptgenerror
2384                         (flag,
2385                          message 
2386                          ("Expression has undefined behavior (both "
2387                           "operands modify %q): %s %s %s", 
2388                           sRef_unparse (sr), 
2389                           exprNode_unparse (e1), 
2390                           lltok_unparse (op), exprNode_unparse (e2)),
2391                          e2->loc);
2392                     }
2393                 }
2394             }
2395         }
2396     } end_sRefSet_realElements;
2397 }
2398
2399 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2400 {
2401   bool hasError = FALSE;
2402   
2403   if (exprNode_isError (e1) || exprNode_isError (e2))
2404     {
2405       return;
2406     }
2407
2408   if (sRefSet_member (e2->sets, e1->sref))
2409     {
2410       if (e2->kind == XPR_CALL)
2411         {
2412          ;
2413         }
2414       else
2415         {
2416           hasError = optgenerror 
2417             (FLG_EVALORDER,
2418              message ("Expression has undefined behavior "
2419                       "(value of left operand %s is modified "
2420                       "by right operand %s): %s %s %s", 
2421                       exprNode_unparse (e1),
2422                       exprNode_unparse (e2),
2423                       exprNode_unparse (e1), lltok_unparse (op),
2424                       exprNode_unparse (e2)),
2425              e2->loc);
2426         }
2427     }
2428
2429   if (context_getFlag (FLG_EVALORDERUNCON))
2430     {
2431       if (sRefSet_member (e2->msets, e1->sref))
2432         {
2433           if (e2->kind == XPR_CALL)
2434             {
2435               ;
2436             }
2437           else
2438             {
2439               hasError = optgenerror 
2440                 (FLG_EVALORDER,
2441                  message 
2442                  ("Expression has undefined behavior (value of left "
2443                   "operand may be modified by right operand): %s %s %s", 
2444                   exprNode_unparse (e1), lltok_unparse (op),
2445                   exprNode_unparse (e2)),
2446                  e2->loc);
2447             }
2448         }
2449     }
2450   
2451   if (!hasError)
2452     {
2453       checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2454       
2455       if (context_maybeSet (FLG_EVALORDERUNCON))
2456         {
2457           checkExpressionDefinedAux (e1, e2, e1->msets, 
2458                                      e2->msets, op, FLG_EVALORDERUNCON);
2459         }
2460     }
2461 }
2462
2463 static void checkSequencing (exprNode p_f, exprNodeList p_args); 
2464
2465 static int
2466   checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl, 
2467                  exprNodeList args, bool isIter, exprNode ret)
2468 {
2469   int special = 0;
2470
2471   if (!exprNode_isError (f))
2472     {
2473       if (!uentryList_isMissingParams (cl))
2474         {
2475           int nargs = exprNodeList_size (args);
2476           int expectargs = uentryList_size (cl);
2477           ctype last;
2478           int i = 0;
2479           
2480           if (expectargs == 0)
2481             {
2482               if (nargs != 0)
2483                 {
2484                   if (isIter)
2485                     {
2486                       voptgenerror
2487                         (FLG_TYPE,
2488                          message ("Iter %q invoked with %d args, "
2489                                   "declared void",
2490                                   uentry_getName (fcn),
2491                                   nargs),
2492                          f->loc);
2493                     }
2494                   else
2495                     {
2496                       voptgenerror 
2497                         (FLG_TYPE,
2498                          message ("Function %s called with %d args, "
2499                                   "declared void", 
2500                                   exprNode_unparse (f), nargs),
2501                          f->loc);
2502                     }
2503                 }
2504               return special;
2505             }
2506           
2507           last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2508           
2509           exprNodeList_reset (args);
2510           
2511           uentryList_elements (cl, current)
2512             {
2513               ctype ct = uentry_getType (current);
2514               exprNode a;
2515               
2516               if (ctype_isElips (ct))
2517                 {
2518                   /*
2519                    ** do special checking for printf/scanf library functions
2520                    **
2521                    ** this is kludgey code, just for handling the special case
2522                    **
2523                    */
2524
2525                   if (uentry_isPrintfLike (fcn))
2526                     {
2527                       checkPrintfArgs (f, fcn, args, ret, i);
2528                       special = i;
2529                     }
2530                   else if (uentry_isScanfLike (fcn))
2531                     {
2532                       checkScanfArgs (f, fcn, args, ret, i); 
2533                       special = i;
2534                     }
2535                   else if (uentry_isMessageLike (fcn))
2536                     {
2537                       checkMessageArgs (f, fcn, args, i);
2538                       special = i;
2539                     }
2540                   else
2541                     {
2542                       llassert (!uentry_isSpecialFunction (fcn));
2543                     }
2544                     
2545                   nargs = expectargs; /* avoid errors */
2546                   break;
2547                 }
2548               else
2549                 {
2550                   if (i >= nargs) break;
2551                   
2552                   a = exprNodeList_current (args);
2553                   exprNodeList_advance (args);
2554                   
2555                   i++;
2556                   
2557                   if (exprNode_isError (a))
2558                     {
2559                      ;
2560                     }
2561                   else
2562                     {
2563                       /* 
2564                         probably necessary? I'm not sure about this one
2565                         checkMacroParen (a);
2566                         */
2567                       
2568                       f->guards = guardSet_union (f->guards, a->guards);
2569                       
2570                       DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2571
2572                       if (!(exprNode_matchArgType (ct, a)))
2573                         {
2574                           DPRINTF (("Args mismatch!"));
2575
2576                           if (ctype_isVoidPointer (ct) 
2577                               && (ctype_isPointer (a->typ) 
2578                                   && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2579                             {
2580                               vnoptgenerror 
2581                                 (FLG_ABSTVOIDP,
2582                                  message 
2583                                  ("Pointer to abstract type (%t) used "
2584                                   "as void pointer "
2585                                   "(arg %d to %q): %s",
2586                                   a->typ, i, 
2587                                   uentry_getName (fcn), 
2588                                   exprNode_unparse (a)),
2589                                  a->loc);
2590                             }
2591                           else
2592                             {
2593                               if (isIter)
2594                                 {
2595                                   (void) gentypeerror 
2596                                     (ct, exprNode_undefined,
2597                                      a->typ, a,
2598                                      message 
2599                                      ("Iter %q expects arg %d to "
2600                                       "be %t gets %t: %s",
2601                                       uentry_getName (fcn),
2602                                       i, ct, a->typ, exprNode_unparse (a)),
2603                                      a->loc);
2604                                 }
2605                               else
2606                                 {
2607                                   if (gentypeerror  
2608                                       (ct, 
2609                                        exprNode_undefined,
2610                                        a->typ,
2611                                        a,
2612                                        message 
2613                                        ("Function %q expects arg %d to be %t gets %t: %s",
2614                                         uentry_getName (fcn),
2615                                         i, ct, a->typ, exprNode_unparse (a)),
2616                                        a->loc))
2617                                     {
2618                                       DPRINTF (("Types: %s / %s",
2619                                                 ctype_unparse (ct),
2620                                                 ctype_unparse (a->typ)));
2621                                     }
2622
2623                                   /*
2624                                   ** Clear null marker for abstract types.
2625                                   ** (It is not revealed, so suppress future messages.)
2626                                   */
2627
2628                                   if (ctype_isAbstract (a->typ))
2629                                     {
2630                                       sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2631                                     }
2632                                 }
2633                             }
2634                         }
2635                     }
2636                 }
2637             } end_uentryList_elements ;
2638           
2639           
2640           if (expectargs != nargs) /* note: not != since we may have ... */
2641             {
2642               if (ctype_isElips (last))
2643                 {
2644                   voptgenerror
2645                     (FLG_TYPE,
2646                      message ("Function %s called with %d args, expects at least %d",
2647                               exprNode_unparse (f),
2648                               nargs, expectargs - 1),
2649                      f->loc);
2650                 }
2651               else
2652                 {
2653                   if (isIter)
2654                     {
2655                       voptgenerror 
2656                         (FLG_TYPE,
2657                          message ("Iter %q invoked with %d args, expects %d",
2658                                   uentry_getName (fcn), nargs, expectargs),
2659                          f->loc);
2660                     }
2661                   else
2662                     {
2663                       voptgenerror 
2664                         (FLG_TYPE,
2665                          message ("Function %s called with %d args, expects %d",
2666                                   exprNode_unparse (f),
2667                                   nargs, expectargs),
2668                          f->loc);
2669                     }
2670                 }
2671             }
2672         }
2673     }
2674
2675   return special;
2676 }
2677
2678 /*
2679 ** Check for undefined code sequences in function arguments:
2680 **
2681 **   one parameter sets something used by another parameter
2682 **   one parameter sets something set  by another parameter
2683 */
2684
2685 static void 
2686 checkSequencingOne (exprNode f, exprNodeList args, 
2687                     /*@notnull@*/ exprNode el, int argno)
2688 {
2689   /*
2690   ** Do second loop, iff +undefunspec
2691   */
2692
2693   int checkloop;
2694   int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2695   
2696   for (checkloop = 0; checkloop < numloops; checkloop++)
2697     {
2698       sRefSet thissets;
2699
2700       if (checkloop == 0)
2701         {
2702           thissets = el->sets;
2703         }
2704       else
2705         {
2706           llassert (checkloop == 1);
2707           thissets = el->msets;
2708         }
2709       
2710       sRefSet_realElements (thissets, thisset)
2711         {
2712           int j;
2713
2714           /*@access exprNodeList@*/
2715           for (j = 0; j < args->nelements; j++)
2716             {
2717               exprNode jl = args->elements[j];
2718               int thisargno = j + 1;
2719
2720               if (thisargno != argno && exprNode_isDefined (jl))
2721                 {
2722                   sRefSet otheruses = jl->uses;
2723                   
2724                   if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) && 
2725                       sRefSet_hasUnconstrained (thissets))
2726                     {
2727                       voptgenerror
2728                         (FLG_EVALORDERUNCON,
2729                          /*@-sefparams@*/
2730                          message
2731                          ("%q used in argument %d may set "
2732                           "global variable %q used by argument %d: %s(%q)", 
2733                           cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2734                           /*@=sefparams@*/
2735                           argno,
2736                           sRef_unparse (sRef_getRootBase (jl->sref)),
2737                           thisargno,
2738                           exprNode_unparse (f), exprNodeList_unparse (args)),
2739                          el->loc);
2740                     }
2741
2742                   if (sRefSet_member (otheruses, thisset))
2743                     {
2744                       if (sRef_isUnconstrained (thisset))
2745                         {
2746                           voptgenerror 
2747                             (FLG_EVALORDERUNCON,
2748                              message 
2749                              ("Unconstrained functions used in arguments %d (%q) "
2750                               "and %d (%s) may modify "
2751                               "or use global state in undefined way: %s(%q)",
2752                               argno,
2753                               sRefSet_unparseUnconstrainedPlain (otheruses),
2754                               thisargno, 
2755                               sRef_unconstrainedName (thisset),
2756                               exprNode_unparse (f), 
2757                               exprNodeList_unparse (args)),
2758                              el->loc);
2759                         }
2760                       else
2761                         {
2762                           voptgenerror 
2763                             (FLG_EVALORDER,
2764                              message 
2765                              ("Argument %d modifies %q, used by argument %d "
2766                               "(order of evaluation of actual parameters is "
2767                               "undefined): %s(%q)",
2768                               argno, sRef_unparse (thisset), thisargno, 
2769                               exprNode_unparse (f), exprNodeList_unparse (args)),
2770                              el->loc);
2771                         }
2772                     }
2773                   else 
2774                     {
2775                       sRefSet othersets = jl->sets;
2776                       
2777                       if (sRefSet_member (othersets, thisset))
2778                         {
2779                           if (sRef_isUnconstrained (thisset))
2780                             {
2781                               voptgenerror 
2782                                 (FLG_EVALORDERUNCON,
2783                                  message 
2784                                  ("Unconstrained functions used in "
2785                                   "arguments %d (%q) and %d (%s) may modify "
2786                                   "or use global state in undefined way: %s(%q)",
2787                                   argno, 
2788                                   sRefSet_unparseUnconstrainedPlain (othersets),
2789                                   thisargno, 
2790                                   sRef_unconstrainedName (thisset),
2791                                   exprNode_unparse (f), exprNodeList_unparse (args)),
2792                                  el->loc);
2793                             }
2794                           else
2795                             {
2796                               voptgenerror 
2797                                 (FLG_EVALORDER,
2798                                  message 
2799                                  ("Argument %d modifies %q, set by argument %d (order of"
2800                                   " evaluation of actual parameters is undefined): %s(%q)",
2801                                   argno, sRef_unparse (thisset), thisargno, 
2802                                   exprNode_unparse (f), exprNodeList_unparse (args)),
2803                                  el->loc);
2804                             }
2805                         }
2806                     }
2807                 }
2808             }
2809           /*@noaccess exprNodeList@*/
2810         } end_sRefSet_realElements;
2811     }
2812 }
2813
2814 static void
2815 checkSequencing (exprNode f, exprNodeList args)
2816 {
2817   if (exprNodeList_size (args) > 1)
2818     {
2819       int i;
2820       exprNode el;
2821       
2822       /*@access exprNodeList*/
2823       
2824       for (i = 0; i < args->nelements; i++)
2825         {
2826           el = args->elements[i];
2827           
2828           if (!exprNode_isError (el))
2829             {
2830               checkSequencingOne (f, args, el, i + 1);
2831             }
2832         }
2833       /*@noaccess exprNodeList*/
2834     }
2835 }
2836
2837 /*
2838 ** requires le = exprNode_getUentry (f) 
2839 */
2840
2841 static void
2842 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2843                uentry le, exprNodeList args, 
2844                /*@notnull@*/ exprNode ret, int specialArgs)
2845 {
2846   bool isSpec = FALSE;
2847   bool hasMods = FALSE;
2848   cstring fname;
2849   globSet usesGlobs = globSet_undefined;
2850   sRefSet mods = sRefSet_undefined;
2851   bool freshMods = FALSE;
2852   uentryList params = uentryList_undefined;
2853
2854   DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2855
2856   /*
2857   ** check globals and modifies
2858   */
2859
2860   setCodePoint ();
2861   
2862   if (!uentry_isValid (le))
2863     {
2864       ctype fr = ctype_realType (f->typ);
2865
2866       if (ctype_isFunction (fr))
2867         {
2868           params = ctype_argsFunction (fr);
2869         }
2870       else
2871         {
2872           params = uentryList_missingParams;
2873         }
2874
2875       if (!context_getFlag (FLG_MODNOMODS) 
2876           && !context_getFlag (FLG_GLOBUNSPEC))
2877         {
2878           checkUnspecCall (f, params, args);
2879         }
2880       
2881       return;
2882     }
2883
2884   fname = uentry_rawName (le);
2885
2886   setCodePoint ();
2887
2888   if (uentry_isFunction (le))
2889     {
2890       params = uentry_getParams (le);
2891       mods = uentry_getMods (le);
2892       hasMods = uentry_hasMods (le);
2893       usesGlobs = uentry_getGlobs (le);
2894       isSpec = uentry_isSpecified (le);
2895     }
2896   else /* not a function */
2897     {
2898       ctype ct = ctype_realType (uentry_getType (le));
2899       
2900       llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2901                      ("checkModGlobs: uentry not a function: %s", 
2902                       uentry_unparse (le)));
2903       
2904       params = ctype_argsFunction (ct);
2905       return; /*@32 ! remove this? */
2906     }
2907
2908   /*
2909   ** check globals
2910   */
2911
2912   setCodePoint ();
2913     
2914   globSet_allElements (usesGlobs, el)
2915     {
2916       if (sRef_isValid (el))
2917         {
2918           if (sRef_isInternalState (el) || sRef_isSystemState (el))
2919             {
2920               context_usedGlobal (el);
2921               exprNode_checkUse (f, el, f->loc);
2922
2923               if (context_checkInternalUse ())
2924                 {
2925                   if (!context_globAccess (el))
2926                     {
2927                       if (sRef_isSystemState (el)
2928                           && !context_getFlag (FLG_MODFILESYSTEM))
2929                         {
2930                           ;
2931                         }
2932                       else
2933                         {
2934                           voptgenerror
2935                             (FLG_INTERNALGLOBS,
2936                              message 
2937                              ("Called procedure %s may access %q, but "
2938                               "globals list does not include globals %s",
2939                               exprNode_unparse (f),
2940                               sRef_unparse (el),
2941                               cstring_makeLiteralTemp (sRef_isInternalState (el)
2942                                                        ? "internalState"
2943                                                        : "fileSystem")),
2944                              f->loc);
2945                         }
2946                     }
2947                 }
2948             }
2949           else if (sRef_isNothing (el) || sRef_isSpecState (el))
2950             {
2951               ;
2952             }
2953           else
2954             {
2955               uentry gle = sRef_getUentry (el);
2956               sRef sr = sRef_updateSref (el);
2957               
2958               if (sRef_isUndefGlob (el))
2959                 {
2960                   sRef_setDefined (sr, f->loc);
2961                   exprNode_checkSet (f, sr);
2962                 }
2963               else
2964                 {
2965                   /*
2966                   ** check definition
2967                   */
2968                   
2969                   if (sRef_isAllocated (el))
2970                     {
2971                       exprNode_checkSet (f, sr);
2972                     }
2973                   else
2974                     {
2975                       if (sRef_isStateUndefined (sr))
2976                         {
2977                           voptgenerror 
2978                             (FLG_GLOBSTATE,
2979                              message
2980                              ("%s %q used by function undefined before call: %s",
2981                               sRef_getScopeName (sr),
2982                               sRef_unparse (sr),
2983                               exprNode_unparse (f)),
2984                              f->loc);
2985                           sRef_setDefined (sr, f->loc);
2986                         }
2987                       exprNode_checkUse (f, sr, f->loc);
2988                     }
2989                   
2990                   checkGlobUse (gle, TRUE, f);
2991                 }
2992           
2993               if (sRef_isKilledGlob (el))
2994                 {
2995                   sRef_kill (sr, f->loc);
2996                   context_usedGlobal (sr);
2997                 }
2998             }
2999         }
3000     } end_globSet_allElements;
3001   
3002   /*
3003   ** check modifies
3004   */
3005
3006   if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
3007     {
3008       sRefSet smods = sRefSet_undefined;
3009
3010       /*
3011       ** NEED to check for modifies anything
3012       */
3013
3014       /*
3015       ** check each sRef that called function modifies (ml), is
3016       ** modifiable by tl
3017       */
3018
3019       setCodePoint ();
3020
3021       sRefSet_allElements (mods, s) /* s is something which may be modified */
3022         {
3023           DPRINTF (("Check modify: %s", sRef_unparse (s)));
3024
3025           if (sRef_isKindSpecial (s))
3026             {
3027               if (sRef_isSpecInternalState (s))
3028                 {
3029                   if (context_getFlag (FLG_MODINTERNALSTRICT))
3030                     {
3031                       exprNode_checkCallModifyVal (s, args, f, ret);
3032                     }
3033                   else
3034                     {
3035                       sRefSet mmods = context_modList ();
3036
3037                       sRefSet_allElements (mmods, el)
3038                         {
3039                           if (sRef_isInternalState (el))
3040                             {
3041                               sRef_setModified (el);
3042                             }
3043                         } end_sRefSet_allElements ;
3044                     }
3045                 }
3046               else
3047                 {
3048                   exprNode_checkCallModifyVal (s, args, f, ret);
3049                 }
3050             }
3051           else
3052             {
3053               sRef rb = sRef_getRootBase (s);
3054               
3055               if (sRef_isFileOrGlobalScope (rb))
3056                 {
3057                   context_usedGlobal (rb);
3058                 }
3059               
3060               if (sRef_isFileStatic (s)
3061                   && !fileId_equal (fileloc_fileId (f->loc), 
3062                                     fileloc_fileId (uentry_whereDefined (le))))
3063                 {
3064                   smods = sRefSet_insert (smods, s);
3065                 }
3066               else
3067                 {
3068                   exprNode_checkCallModifyVal (s, args, f, ret);
3069                 }
3070             }
3071         } end_sRefSet_allElements;
3072
3073       setCodePoint ();
3074
3075       /*
3076       ** Static elements in modifies set can have nasty consequences.
3077       ** (I think...have not been able to reproduce a possible bug.)
3078       */
3079
3080       if (!sRefSet_isDefined (smods))
3081         {
3082           mods = sRefSet_newCopy (mods);
3083           freshMods = TRUE;
3084           
3085           sRefSet_allElements (smods, el)
3086             {
3087               bool res = sRefSet_delete (mods, el);
3088               
3089               llassert (res);
3090             } end_sRefSet_allElements;
3091
3092           sRefSet_free (smods);
3093         /*@-branchstate@*/
3094         } 
3095       /*@=branchstate@*/
3096     }
3097   else if (sRefSet_isDefined (mods))
3098     { /* just check observers */
3099       setCodePoint ();
3100
3101       sRefSet_allElements (mods, s) /* s is something which may be modified */
3102         {
3103           sRef rb = sRef_getRootBase (s);
3104
3105           setCodePoint ();
3106
3107           if (sRef_isParam (rb))
3108             {
3109               sRef b = sRef_fixBaseParam (s, args);
3110
3111               if (sRef_isObserver (b))
3112                 {
3113                   exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3114                   
3115                   if (optgenerror 
3116                       (FLG_MODOBSERVER,
3117                        message ("Function call may modify observer%q: %s", 
3118                                 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3119                        exprNode_loc (e)))
3120                     {
3121                       sRef_showExpInfo (b);
3122                     }
3123                 }
3124             }
3125         } end_sRefSet_allElements;
3126     }
3127   else 
3128     {
3129       if (!hasMods) /* no specified modifications */
3130         {
3131           if (context_getFlag (FLG_MODOBSERVERUNCON))
3132             {
3133               exprNodeList_elements (args, e)
3134                 {
3135                   if (exprNode_isDefined (e))
3136                     {
3137                       sRef s = exprNode_getSref (e);
3138                       
3139                       if (sRef_isObserver (s) 
3140                           && ctype_isMutable (sRef_getType (s)))
3141                         {
3142                           if (optgenerror 
3143                               (FLG_MODOBSERVERUNCON,
3144                                message
3145                                ("Call to unconstrained function %s may modify observer%q: %s", 
3146                                 exprNode_unparse (f),
3147                                 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3148                                exprNode_loc (e)))
3149                             {
3150                               sRef_showExpInfo (s);
3151                             }
3152                         }
3153                     }
3154                 } end_exprNodeList_elements; 
3155             }
3156         }
3157     }
3158   
3159   checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3160
3161   ret->uses = sRefSet_union (ret->uses, f->uses);
3162   ret->sets = sRefSet_union (ret->sets, f->sets);
3163   ret->msets = sRefSet_union (ret->msets, f->msets);
3164
3165   if (freshMods)
3166     {
3167       /*
3168       ** Spurious errors reported, because splint can't tell
3169       ** mods must be fresh if freshMods is true.
3170       */
3171
3172       /*@i@*/ sRefSet_free (mods);
3173     }
3174
3175   setCodePoint ();
3176 }
3177
3178 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3179 {
3180   if (uentry_isVar (glob))
3181     {
3182       if (context_inFunctionLike ())
3183         {
3184           sRef sr = uentry_getSref (glob);
3185
3186           context_usedGlobal (sr);
3187           
3188           if (context_checkGlobUse (glob))
3189             {
3190               if (!context_globAccess (sr))
3191                 {
3192                   if (isCall)
3193                     {
3194                       voptgenerror
3195                         (FLG_GLOBALS,
3196                          message ("Called procedure %s may access %s %q",
3197                                   exprNode_unparse (e), 
3198                                   sRef_unparseScope (sr),
3199                                   uentry_getName (glob)),
3200                          e->loc);
3201                     }
3202                   else
3203                     {
3204                       voptgenerror 
3205                         (FLG_GLOBALS,
3206                          message ("Undocumented use of %s %s", 
3207                                   sRef_unparseScope (sr),
3208                                   exprNode_unparse (e)),
3209                          e->loc);
3210                     }
3211                 }
3212             }
3213         }
3214     }
3215   else
3216     {
3217       llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3218     }
3219 }  
3220
3221 static void
3222 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3223 {
3224   DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3225             exprNode_unparse (f), exprNodeList_unparse (args),
3226             uentry_unparseFull (le),
3227             stateClauseList_unparse (uentry_getStateClauseList (le))));
3228
3229   if (uentry_isValid (le) && uentry_isFunction (le))
3230     {
3231       stateClauseList sclauses = uentry_getStateClauseList (le);
3232
3233       if (stateClauseList_isDefined (sclauses))
3234         {
3235           DPRINTF (("Reflect ensures: %s / %s / %s",
3236                     uentry_unparse (le),
3237                     exprNode_unparse (f), exprNodeList_unparse (args)));
3238           
3239           stateClauseList_elements (sclauses, cl) 
3240             {
3241               if (stateClause_hasEnsures (cl))
3242                 {
3243                   /* Same in usymtab.c:1904 */
3244                   if (stateClause_setsMetaState (cl))
3245                     {
3246                       qual q = stateClause_getMetaQual (cl);
3247                       annotationInfo ainfo = qual_getAnnotationInfo (q);
3248                       metaStateInfo minfo = annotationInfo_getState (ainfo);
3249                       cstring key = metaStateInfo_getName (minfo);
3250                       int mvalue = annotationInfo_getValue (ainfo);
3251
3252                       sRefSet osrs = sRefSet_undefined;
3253                       sRefSet srs;
3254                       
3255                       if (stateClause_isGlobal (cl))
3256                         {
3257                           srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3258                           osrs = srs;
3259                         }
3260                       else
3261                         {
3262                           srs = stateClause_getRefs (cl);
3263                         }
3264                       
3265                       DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3266                       
3267                       
3268                       DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3269                       
3270                       sRefSet_elements (srs, sel)
3271                         {
3272                           sRef s;
3273                           
3274                           if (sRef_isResult (sRef_getRootBase (sel)))
3275                             {
3276                               s = exprNode_getSref (ret);
3277                             }
3278                           else 
3279                             {
3280                               s = sRef_fixBaseParam (sel, args);
3281                             }
3282
3283                           DPRINTF (("Reflecting state clause on: %s / %s",
3284                                     sRef_unparse (sel), sRef_unparse (s)));
3285                           
3286                           sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3287                         } end_sRefSet_elements;
3288
3289                       sRefSet_free (osrs);
3290                     }
3291                   else
3292                     {
3293                       sRefSet srs = stateClause_getRefs (cl);
3294                       sRefModVal modf = stateClause_getEnsuresFunction (cl);
3295                       int eparam = stateClause_getStateParameter (cl);
3296                       
3297                       DPRINTF (("Reflect after clause: %s / %s", 
3298                                 stateClause_unparse (cl),
3299                                 sRefSet_unparse (srs)));
3300                       
3301                       sRefSet_elements (srs, sel)
3302                         {
3303                           sRef s;
3304                           
3305                           DPRINTF (("elements: %s", sRef_unparse (sel)));
3306                           DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3307                           
3308                           if (sRef_isResult (sRef_getRootBase (sel)))
3309                             {
3310                               DPRINTF (("Fix base: %s / %s",
3311                                         sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3312                               s = sRef_fixBase (sel, exprNode_getSref (ret));
3313                               DPRINTF (("==> %s", sRef_unparseFull (s)));
3314                             }
3315                           else
3316                             {
3317                               s = sRef_fixBaseParam (sel, args);
3318                             }
3319
3320                           DPRINTF (("elements: %s", sRef_unparse (s)));
3321                           DPRINTF (("elements: %s", sRef_unparseFull (s)));
3322                           
3323                           DPRINTF (("Reflecting state clause on: %s / %s",
3324                                     sRef_unparseFull (sel), sRef_unparseFull (s)));
3325                           
3326                           /* evans 2001-08-24 - added aliasSetCompleteParam */
3327                           sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3328
3329                           DPRINTF (("After reflecting state clause on: %s / %s",
3330                                     sRef_unparseFull (sel), sRef_unparseFull (s)));
3331                         } end_sRefSet_elements;
3332                     }
3333                 }
3334             } end_stateClauseList_elements ;        
3335         }
3336
3337       DPRINTF (("Here: %s / %s",
3338                 uentry_unparseFull (le),
3339                 bool_unparse (uentry_hasMetaStateEnsures (le))));
3340
3341       if (uentry_hasMetaStateEnsures (le))
3342         {
3343           fileloc loc = exprNode_loc (f);
3344
3345           metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3346
3347           metaStateConstraintList_elements (mscl, msc)
3348             {
3349               metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3350               metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3351               metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3352               cstring key = metaStateInfo_getName (msinfo);           
3353               sRef mlsr = metaStateSpecifier_getSref (msspec);
3354               sRef s;
3355               sRef lastref = sRef_undefined;
3356               stateValue sval = stateValue_undefined;
3357               
3358               DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3359                         metaStateConstraint_unparse (msc)));
3360               DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3361               
3362               if (sRef_isResult (sRef_getRootBase (mlsr)))
3363                 {
3364                   s = exprNode_getSref (ret);
3365                 }
3366               else
3367                 {
3368                   s = sRef_fixBaseParam (mlsr, args);
3369                 }
3370               
3371               DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3372               
3373               while (metaStateExpression_isDefined (msexpr)) 
3374                 {
3375                   metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3376                   metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3377                   sRef msr, fs;
3378
3379                   DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3380                   
3381                   if (metaStateExpression_isMerge (msexpr))
3382                     {
3383                       msexpr = metaStateExpression_getRest (msexpr);
3384                     }
3385                   else
3386                     {
3387                       msexpr = metaStateExpression_undefined;
3388                     }
3389                   
3390                   if (metaStateInfo_isDefined (msi))
3391                     {
3392                       /* Must match lhs state */
3393                       llassert (metaStateInfo_equal (msinfo, msi));
3394                     }
3395                   
3396                   if (metaStateSpecifier_isElipsis (ms))
3397                     {
3398                       /*
3399                       ** For elipsis, we need to merge all the relevant elipsis parameters
3400                       ** 
3401                       */
3402                       
3403                       uentryList params = uentry_getParams (le);
3404                       int paramno = uentryList_size (params) - 1;
3405
3406                       if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3407                         {
3408                           voptgenerror 
3409                             (FLG_TYPE,
3410                              message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3411                                       uentry_getName (le)),
3412                              uentry_whereLast (le));
3413                           /*@innerbreak@*/ break;
3414                         }
3415
3416                       while (paramno < exprNodeList_size (args))
3417                         {
3418                           exprNode arg = exprNodeList_getN (args, paramno);
3419                           fs = exprNode_getSref (arg);
3420                           DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3421
3422                           /* cut and pasted... gack*/
3423                           if (stateValue_isDefined (sval))
3424                             {
3425                               /* Use combination table to merge old state value with new one: */
3426                               stateValue tval = sRef_getMetaStateValue (fs, key);
3427                               
3428                               if (stateValue_isDefined (tval))
3429                                 {
3430                                   stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3431                                   cstring msg = cstring_undefined;
3432                                   int nval = stateCombinationTable_lookup (sctable, 
3433                                                                            stateValue_getValue (sval), 
3434                                                                            stateValue_getValue (tval), 
3435                                                                            &msg);
3436                                   DPRINTF (("Combining: %s + %s -> %d",
3437                                             stateValue_unparseValue (sval, msinfo),
3438                                             stateValue_unparseValue (tval, msinfo),
3439                                             nval));
3440                                   
3441                                   if (nval == stateValue_error)
3442                                     {
3443                                       if (optgenerror 
3444                                           (FLG_STATEMERGE,
3445                                            message
3446                                            ("Attributes merged in ensures clause in states that "
3447                                             "cannot be combined (%q is %q, %q is %q)%q",
3448                                             sRef_unparse (lastref),
3449                                             stateValue_unparseValue (sval, msinfo),
3450                                             sRef_unparse (fs),
3451                                             stateValue_unparseValue (tval, msinfo),
3452                                             cstring_isDefined (msg) ? 
3453                                             message (": %s", msg) : cstring_undefined),
3454                                            exprNode_loc (f)))
3455                                         {
3456                                           sRef_showMetaStateInfo (fs, key);
3457                                         }                   
3458                                     }
3459                                   
3460                                   stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3461                                   loc = exprNode_loc (arg);
3462                                 }
3463                               else
3464                                 {
3465                                   DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3466                                 }
3467                             }
3468                           else
3469                             {
3470                               sval = sRef_getMetaStateValue (fs, key);
3471                             }
3472                           
3473                           lastref = fs;
3474                           
3475                           if (stateValue_isError (sval))
3476                             {
3477                               /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3478                             }
3479                         
3480                           
3481                           paramno++;
3482                         }
3483                     }
3484                   else
3485                     {
3486                       msr = metaStateSpecifier_getSref (ms);
3487                   
3488                       
3489                       llassert (sRef_isParam (sRef_getRootBase (msr)));
3490                       fs = sRef_fixBaseParam (msr, args);
3491                       
3492                       if (stateValue_isDefined (sval))
3493                         {
3494                           /* Use combination table to merge old state value with new one: */
3495                           stateValue tval = sRef_getMetaStateValue (fs, key);
3496                           
3497                           if (stateValue_isDefined (tval))
3498                             {
3499                               stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3500                               cstring msg = cstring_undefined;
3501                               int nval = stateCombinationTable_lookup (sctable, 
3502                                                                        stateValue_getValue (sval), 
3503                                                                        stateValue_getValue (tval), 
3504                                                                        &msg);
3505                               DPRINTF (("Combining: %s + %s -> %d",
3506                                         stateValue_unparseValue (sval, msinfo),
3507                                         stateValue_unparseValue (tval, msinfo),
3508                                         nval));
3509                               
3510                               if (nval == stateValue_error)
3511                                 {
3512                                   if (optgenerror 
3513                                       (FLG_STATEMERGE,
3514                                        message
3515                                        ("Attributes merged in ensures clause in states that "
3516                                         "cannot be combined (%q is %q, %q is %q)%q",
3517                                         sRef_unparse (lastref),
3518                                         stateValue_unparseValue (sval, msinfo),
3519                                         sRef_unparse (fs),
3520                                         stateValue_unparseValue (tval, msinfo),
3521                                         cstring_isDefined (msg) 
3522                                         ? message (": %s", msg) : cstring_undefined),
3523                                        exprNode_loc (f)))
3524                                     {
3525                                       sRef_showMetaStateInfo (fs, key);
3526                                     }               
3527                                 }
3528                               
3529                               stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3530                             }
3531                           else
3532                             {
3533                               DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3534                             }
3535                         }
3536                       else
3537                         {
3538                           sval = sRef_getMetaStateValue (fs, key);
3539                         }
3540                       
3541                       lastref = fs;
3542                       
3543                       if (stateValue_isError (sval))
3544                         {
3545                           /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3546                         }
3547                     }
3548                 }
3549
3550               DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3551               
3552               if (stateValue_isDefined (sval))
3553                 {
3554                   sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3555                 }
3556               else
3557                 {
3558                   DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3559                 }
3560             } end_metaStateConstraintList_elements ;
3561
3562           metaStateConstraintList_free (mscl);
3563         }
3564     }
3565 }
3566
3567 static void
3568 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3569 {
3570   DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3571             exprNode_unparse (f), exprNodeList_unparse (args),
3572             uentry_unparseFull (le),
3573             stateClauseList_unparse (uentry_getStateClauseList (le))));
3574   
3575   if (uentry_isValid (le) && uentry_isFunction (le))
3576     {
3577       stateClauseList sclauses = uentry_getStateClauseList (le);
3578       
3579       if (stateClauseList_isDefined (sclauses))
3580         {
3581           DPRINTF (("Check requires: %s / %s / %s",
3582                     uentry_unparse (le),
3583                     exprNode_unparse (f), exprNodeList_unparse (args)));
3584           
3585           stateClauseList_elements (sclauses, cl) 
3586             {
3587               DPRINTF (("Check clause: %s / %s",
3588                         stateClause_unparse (cl),
3589                         bool_unparse (stateClause_hasRequires (cl))));
3590
3591               if (stateClause_hasRequires (cl))
3592                 {
3593                   sRefSet osrs = sRefSet_undefined;
3594                   sRefSet srs;
3595
3596                   if (stateClause_isGlobal (cl))
3597                     {
3598                       srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3599                       osrs = srs;
3600                     }
3601                   else
3602                     {
3603                       srs = stateClause_getRefs (cl);
3604                     }
3605
3606                   DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3607
3608                   if (stateClause_setsMetaState (cl))
3609                     {
3610                       qual q = stateClause_getMetaQual (cl);
3611                       annotationInfo ainfo = qual_getAnnotationInfo (q);
3612                       metaStateInfo minfo = annotationInfo_getState (ainfo);
3613                       cstring key = metaStateInfo_getName (minfo);
3614                       int mvalue = annotationInfo_getValue (ainfo);
3615                       
3616                       DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3617                       
3618                       sRefSet_elements (srs, sel)
3619                         {
3620                           sRef s = sRef_fixBaseParam (sel, args);
3621                           
3622                           if (sRef_isResult (sRef_getRootBase (sel)))
3623                             {
3624                               BADBRANCH;
3625                             }
3626                           else 
3627                             {
3628                               DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3629                                         sRef_unparseFull (sel), sRef_unparseFull (s),
3630                                         key, mvalue));
3631                               
3632                               if (!sRef_checkMetaStateValue (s, key, mvalue))
3633                                 {                       
3634                                   DPRINTF (("HERE: %s", sRef_unparse (s)));
3635                                   if (optgenerror 
3636                                       (FLG_STATETRANSFER,
3637                                        message
3638                                        ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3639                                         uentry_getName (le),
3640                                         sRef_isGlobalMarker (s) 
3641                                            ? message ("") 
3642                                            : message (" by %q", sRef_unparse (s)),
3643                                         stateValue_unparseValue (sRef_getMetaStateValue (s, key), 
3644                                                                  minfo),
3645                                         stateClause_unparse (cl)),
3646                                        exprNode_loc (f)))
3647                                     {
3648                                       sRef_showAliasInfo (s);
3649                                     }
3650                                   else
3651                                     {
3652                                       DPRINTF (("Error supressed!"));
3653                                       DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3654                                       DPRINTF (("Context supress: %s",
3655                                                 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3656                                     }
3657                                 }
3658                             }
3659                         } end_sRefSet_elements;
3660                     }
3661                   else
3662                     {
3663                       sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3664                       int eparam = stateClause_getStateParameter (cl);
3665                       
3666                       DPRINTF (("Reflect after clause: %s / %s", 
3667                                 stateClause_unparse (cl),
3668                                 sRefSet_unparse (srs)));
3669                       
3670                       sRefSet_elements (srs, sel)
3671                         {
3672                           sRef s;
3673                           
3674                           DPRINTF (("elements: %s", sRef_unparse (sel)));
3675                           DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3676                           
3677                           s = sRef_fixBaseParam (sel, args);
3678                           
3679                           DPRINTF (("elements: %s", sRef_unparse (s)));
3680                           DPRINTF (("elements: %s", sRef_unparseFull (s)));
3681                           
3682                           if (sRef_isResult (sRef_getRootBase (sel)))
3683                             {
3684                               ; /*@i423 what do we do about results */
3685                             }
3686                           else
3687                             {
3688                               DPRINTF (("Reflecting state clause on: %s / %s",
3689                                         sRef_unparse (sel), sRef_unparse (s)));
3690                               
3691                               modf (s, eparam, exprNode_loc (f));
3692                             }
3693                         } end_sRefSet_elements;
3694                     }
3695
3696                   sRefSet_free (osrs);
3697                 }
3698             } end_stateClauseList_elements ;        
3699         }
3700     }
3701 }
3702
3703 static /*@only@*/ exprNode
3704 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3705                   ctype t, /*@keep@*/ exprNodeList args)
3706 {
3707   /* requires f is a non-error exprNode, with type function */
3708   cstring fname = exprNode_unparse (f);
3709   uentry le = exprNode_getUentry (f);
3710   exprNode ret = exprNode_createPartialCopy (f);
3711   int special;
3712
3713   setCodePoint ();
3714
3715   DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3716
3717   ret->typ = ctype_getReturnType (t);
3718   ret->kind = XPR_CALL;
3719
3720   ret->edata = exprData_makeCall (f, args);
3721
3722   /*
3723   ** Order of these steps is very important!  
3724   **
3725   ** Must check for argument dependencies before messing up uses and sets.
3726   */
3727
3728   if (context_getFlag (FLG_EVALORDER))
3729     {
3730       exprNodeList_elements (args, current)
3731         {
3732           if (exprNode_isDefined (current))
3733             {
3734               exprNode_addUse (current, current->sref);
3735             }
3736         } end_exprNodeList_elements;
3737
3738       if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3739         {
3740           checkSequencing (f, args); 
3741         }
3742       
3743       exprNodeList_elements (args, current)
3744         {
3745           if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3746             {
3747               exprNode_addUse (ret, sRef_makeDerived (current->sref));
3748             }
3749         } end_exprNodeList_elements ;
3750     }
3751
3752   special = checkArgs (le, f, t, args, ret); 
3753   checkGlobMods (f, le, args, ret, special); 
3754   checkRequiresClause (le, f, args);
3755   setCodePoint ();
3756
3757   if (uentry_isValid (le)
3758       && (uentry_isFunction (le) 
3759           || (uentry_isVariable (le)
3760               && ctype_isFunction (uentry_getType (le)))))
3761     {
3762       exitkind exk = uentry_getExitCode (le);
3763
3764       /* f->typ is already set to the return type */
3765
3766       DPRINTF (("Function: %s", uentry_unparseFull (le)));
3767       ret->sref = uentry_returnedRef (le, args);
3768       DPRINTF (("Returned: %s / %s",
3769                 uentry_unparseFull (le),
3770                 sRef_unparseFull (ret->sref)));
3771       
3772       if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3773         {
3774           qual nullPred = uentry_nullPred (le);
3775
3776           if (qual_isTrueNull (nullPred))
3777             {
3778               exprNode arg = exprNodeList_head (args);
3779
3780               if (exprNode_isDefined (arg))
3781                 {
3782                   ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3783                 }
3784             }
3785           else if (qual_isFalseNull (nullPred))
3786             {
3787               exprNode arg = exprNodeList_head (args);
3788               
3789               if (exprNode_isDefined (arg))
3790                 {
3791                   ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3792                 }
3793             }
3794           else
3795             {
3796               llassert (qual_isUnknown (nullPred));
3797             }
3798         }
3799       
3800       if (exitkind_isConditionalExit (exk))
3801         {
3802           /*
3803           ** True exit is: 
3804           **    if (arg0) then { exit! } else { ; }
3805           ** False exit is:
3806           **    if (arg0) then { ; } else { exit! }
3807           */
3808
3809           exprNode firstArg;
3810
3811           llassert (!exprNodeList_isEmpty (args));
3812           firstArg = exprNodeList_head (args);
3813
3814           if (exprNode_isDefined (firstArg)
3815               && !guardSet_isEmpty (firstArg->guards))
3816             {
3817               usymtab_trueBranch (guardSet_undefined);
3818               usymtab_altBranch (guardSet_undefined);
3819               
3820               if (exitkind_isTrueExit (exk))
3821                 {
3822                   usymtab_popBranches (firstArg, 
3823                                        exprNode_makeMustExit (), 
3824                                        exprNode_undefined,
3825                                        TRUE, TRUEEXITCLAUSE);
3826                 }
3827               else
3828                 {
3829                   usymtab_popBranches (firstArg,
3830                                        exprNode_undefined,
3831                                        exprNode_makeMustExit (), 
3832                                        TRUE, FALSEEXITCLAUSE);
3833                 }
3834             }
3835
3836           ret->exitCode = XK_MAYEXIT;
3837         }
3838       else if (exitkind_mustExit (exk))
3839         {
3840           ret->exitCode = XK_MUSTEXIT;
3841         }
3842       else if (exitkind_couldExit (exk))
3843         {
3844           ret->exitCode = XK_MAYEXIT;
3845         }
3846       else
3847         {
3848           ;
3849         }
3850       
3851       if (cstring_equalLit (fname, "exit"))
3852         {
3853           if (exprNodeList_size (args) == 1)
3854             {
3855               exprNode arg = exprNodeList_head (args);
3856               
3857               if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3858                 {
3859                   long int val = multiVal_forceInt (exprNode_getValue (arg));
3860                   
3861                   if (val != 0)
3862                     {
3863                       voptgenerror
3864                         (FLG_EXITARG,
3865                          message 
3866                          ("Argument to exit has implementation defined behavior: %s",
3867                           exprNode_unparse (arg)),
3868                          exprNode_loc (arg));
3869                     }
3870                 }
3871             }
3872         }
3873     }
3874   else
3875     {
3876       ret->sref = defref;
3877       exprNode_checkSetAny (ret, uentry_rawName (le));
3878     }
3879
3880   DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3881   DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3882   reflectEnsuresClause (ret, le, f, args);
3883   setCodePoint ();
3884
3885   return (ret);
3886 }
3887
3888 /*
3889 ** this is yucky!  should keep the uentry as part of exprNode!
3890 */
3891
3892 uentry exprNode_getUentry (exprNode e)
3893 {
3894   if (exprNode_isError (e))
3895     {
3896       return uentry_undefined;
3897     }
3898   else
3899     {
3900       cstring s = exprNode_rootVarName (e);
3901       uentry ue = usymtab_lookupSafe (s);
3902
3903       return ue;
3904     }
3905 }
3906
3907 /*
3908 ** Returns true iff e1 and e2 are both exactly the same storage
3909 ** (conservative).
3910 */
3911
3912 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3913 {
3914   sRef s1 = exprNode_getSref (e1);
3915   sRef s2 = exprNode_getSref (e2);
3916   
3917   return (sRef_realSame (s1, s2));
3918 }
3919
3920 exprNode 
3921 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3922 {
3923   exprNode ret = exprNode_createPlain (ctype_unknown);
3924
3925   ret->kind = XPR_INITBLOCK;
3926   ret->edata = exprData_makeCall (exprNode_undefined, inits);
3927   ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3928
3929   return (ret);
3930 }
3931
3932 exprNode
3933 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3934 {
3935   ctype t;
3936
3937   setCodePoint ();
3938
3939   if (exprNode_isUndefined (f))
3940     {
3941       exprNode_free (f);
3942       exprNodeList_free (args);
3943       return exprNode_undefined;
3944     }
3945
3946   t = exprNode_getType (f);
3947
3948   if (sRef_isLocalVar (f->sref))
3949     {
3950       exprNode_checkUse (f, f->sref, f->loc);
3951
3952       if (sRef_possiblyNull (f->sref))
3953         {
3954           if (!usymtab_isGuarded (f->sref))
3955             {
3956               if (optgenerror (FLG_NULLDEREF,
3957                                message ("Function call using %s pointer %q", 
3958                                         sRef_nullMessage (f->sref),
3959                                         sRef_unparse (f->sref)),
3960                                f->loc))
3961                 {
3962                   sRef_showNullInfo (f->sref);
3963                   sRef_setNullError (f->sref);
3964                 }
3965             }
3966         }
3967     }
3968
3969   setCodePoint ();
3970
3971   if (ctype_isRealFunction (t))
3972     {
3973       exprNode ret = functionCallSafe (f, t, args);
3974       setCodePoint ();
3975       return ret;
3976     }
3977   else if (ctype_isUnknown (t))
3978     {
3979       exprNode ret = exprNode_createPartialCopy (f);
3980       cstring tstring;
3981
3982       setCodePoint ();
3983       
3984       ret->typ = t;
3985       exprNodeList_elements (args, current)
3986         {
3987           if (exprNode_isDefined (current))
3988             {
3989               exprNode_checkUse (ret, current->sref, ret->loc);
3990
3991               /* 
3992               ** also, anything derivable from current->sref may be used 
3993               */
3994
3995               exprNode_addUse (ret, sRef_makeDerived (current->sref));
3996               exprNode_mergeUSs (ret, current);
3997             }
3998         } end_exprNodeList_elements;
3999
4000       ret->edata = exprData_makeCall (f, args);
4001       ret->kind = XPR_CALL;
4002
4003       tstring = cstring_copy (exprNode_unparse (f));
4004
4005       cstring_markOwned (tstring);
4006       exprNode_checkSetAny (ret, tstring);
4007
4008       return (ret);
4009     }
4010   else
4011     {
4012       voptgenerror (FLG_TYPE,
4013                     message ("Call to non-function (type %t): %s", t, 
4014                              exprNode_unparse (f)),
4015                     f->loc);
4016       exprNode_free (f);
4017       exprNodeList_free (args);
4018
4019       return (exprNode_makeError ());
4020     }
4021 }
4022
4023 static exprNode
4024 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4025                          /*@only@*/ cstring f)
4026 {
4027   exprNode ret = exprNode_createPartialCopy (s);
4028
4029   ret->kind = XPR_FACCESS;
4030
4031   if (exprNode_isError (s))
4032     {
4033       ret->edata = exprData_makeField (s, f);
4034       return ret;
4035     }
4036   else
4037     {
4038       ctype t = exprNode_getType (s);
4039       ctype tr = ctype_realType (t);
4040
4041       checkMacroParen (s);
4042
4043       ret->edata = exprData_makeField (s, f);
4044
4045       if (ctype_isStructorUnion (tr))
4046         {
4047           uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4048
4049           if (uentry_isUndefined (tf))
4050             {
4051               voptgenerror (FLG_TYPE,
4052                             message ("Access non-existent field %s of %t: %s", f, t, 
4053                                      exprNode_unparse (ret)),
4054                             loc);
4055               /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4056               return (ret);
4057             }
4058           else
4059             {
4060               uentry_setUsed (tf, exprNode_loc (ret));
4061
4062               ret->typ = uentry_getType (tf); 
4063               checkSafeUse (ret, s->sref);
4064               
4065               ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4066               /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4067               return (ret);
4068             }
4069         }
4070       else /* isStructorUnion */
4071         {
4072           if (ctype_isRealAbstract (tr))
4073             {
4074               voptgenerror
4075                 (FLG_ABSTRACT,
4076                  message ("Access field of abstract type (%t): %s.%s", 
4077                           t, exprNode_unparse (s), f),
4078                  loc);
4079               ret->typ = ctype_unknown;
4080             }
4081           else
4082             {
4083               if (ctype_isKnown (tr))
4084                 {
4085                   voptgenerror 
4086                     (FLG_TYPE,
4087                      message
4088                      ("Access field of non-struct or union (%t): %s.%s",
4089                       t, exprNode_unparse (s), f),
4090                      loc);
4091
4092                   ret->typ = ctype_unknown;
4093                 }
4094               else
4095                 {
4096                   cstring sn = cstring_copy (f);
4097                   
4098                   checkSafeUse (ret, s->sref);
4099                   cstring_markOwned (sn);
4100                   ret->sref = sRef_makeField (s->sref, sn);
4101                   return (ret);
4102                 }
4103             }
4104
4105           return (ret);
4106         }
4107     }
4108   BADEXIT;
4109 }
4110
4111 exprNode
4112 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4113                       /*@only@*/ cstring f)
4114 {
4115   exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4116   lltok_release (dot);
4117   return res;
4118 }
4119
4120 exprNode
4121 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4122 {
4123   exprNode ret = exprNode_createPartialCopy (e);
4124
4125   ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4126   ret->kind = XPR_PARENS;
4127   ret->edata = exprData_makeUop (e, lpar);
4128
4129   if (!exprNode_isError (e))
4130     {
4131       ret->exitCode = e->exitCode;
4132       ret->canBreak = e->canBreak;
4133       ret->mustBreak = e->mustBreak;
4134       ret->isJumpPoint = e->isJumpPoint;
4135       ret->sref = e->sref;
4136     }
4137
4138   return ret;
4139 }
4140
4141 static exprNode
4142 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4143                          /*@only@*/ cstring f)
4144 {
4145   exprNode ret = exprNode_createPartialCopy (s);
4146
4147   ret->edata = exprData_makeField (s, f);
4148   ret->kind = XPR_ARROW;
4149   
4150   if (exprNode_isError (s))
4151     {
4152       return (ret);
4153     }
4154   else
4155     {
4156       ctype t = exprNode_getType (s);
4157       ctype tr = ctype_realType (t);
4158       
4159       checkMacroParen (s);
4160       
4161       (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4162       
4163       if (ctype_isRealPointer (tr)) 
4164         {
4165           ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4166           
4167           if (ctype_isStructorUnion (b))
4168             {
4169               uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4170               
4171               if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4172                 {
4173                   if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4174                     {
4175                       if (optgenerror 
4176                           (FLG_NULLDEREF,
4177                            message ("Arrow access from %s pointer%q: %s", 
4178                                     sRef_nullMessage (s->sref),
4179                                     sRef_unparsePreOpt (s->sref),
4180                                     exprNode_unparse (ret)),
4181                            loc))
4182                         {
4183                           sRef_showNullInfo (s->sref);
4184                           sRef_setNullError (s->sref);
4185                         }
4186                     }
4187                 }
4188               
4189               if (uentry_isUndefined (fentry))
4190                 {
4191                   voptgenerror 
4192                     (FLG_TYPE,
4193                      message ("Access non-existent field %s of %t: %s", 
4194                               f, t, exprNode_unparse (ret)),
4195                      loc);
4196                   ret->typ = ctype_unknown;
4197                   return (ret);
4198                 }
4199               else
4200                 {
4201                   /*
4202                   ** was safeUse: shouldn't be safe!
4203                   **
4204                   ** to do rec->field
4205                   ** rec must be defined,
4206                   ** *rec must be allocated
4207                   ** rec->field need only be defined it if is an rvalue
4208                   */
4209                   
4210                   uentry_setUsed (fentry, exprNode_loc (ret));
4211                   ret->typ = uentry_getType (fentry);
4212                   
4213                   exprNode_checkUse (ret, s->sref, s->loc);
4214                   
4215                   /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4216                   ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4217                   return (ret);
4218                 }
4219             }
4220           else /* Pointer to something that is not a struct or union*/
4221             {
4222               if (ctype_isRealAbstract (tr))
4223                 {
4224                   ctype xrt = ctype_forceRealType (tr);
4225                   
4226                   voptgenerror 
4227                     (FLG_ABSTRACT,
4228                      message ("Arrow access field of abstract type (%t): %s->%s", 
4229                               t, exprNode_unparse (s), f),
4230                      loc);
4231                   
4232                   /*
4233                   ** Set the state correctly, as if the abstraction is broken.
4234                   */
4235                   
4236                   if (ctype_isRealPointer (xrt) &&
4237                       (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4238                        ctype_isStructorUnion (b)))
4239                     {
4240                       uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4241                       ret->typ = uentry_getType (fentry);
4242                       ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4243                     }
4244                   else
4245                     {
4246                       ret->typ = ctype_unknown;
4247                       ret->sref = sRef_undefined;
4248                     }
4249                 }
4250               else /* not a struct, union or abstract */
4251                 {
4252                   if (ctype_isUnknown (tr)) {
4253                     cstring sn = cstring_copy (f);
4254                     
4255                     DPRINTF (("Here: %s", exprNode_unparse (s)));
4256                     
4257                     exprNode_checkUse (ret, s->sref, s->loc);
4258                     exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4259                     
4260                     cstring_markOwned (sn);
4261                     ret->sref = sRef_makeArrow (s->sref, sn);
4262                     
4263                     ret->kind = XPR_ARROW;
4264                     return (ret);
4265                   } else {
4266                     voptgenerror 
4267                       (FLG_TYPE,
4268                        message ("Arrow access field of non-struct or union "
4269                                 "pointer (%t): %s->%s",
4270                                 t, exprNode_unparse (s), f),
4271                        loc);
4272                     
4273                     ret->typ = ctype_unknown;
4274                     ret->sref = sRef_undefined;
4275                   }
4276                 }
4277             }
4278         }
4279       else /* its not a pointer */
4280         {
4281           if (!ctype_isUnknown (tr))
4282             {
4283               voptgenerror 
4284                 (FLG_TYPE,
4285                  message ("Arrow access of non-pointer (%t): %s->%s",
4286                           t, exprNode_unparse (s), f),
4287                  loc);
4288               
4289               ret->typ = ctype_unknown;
4290               ret->sref = sRef_undefined;
4291             }
4292           else
4293             {
4294               cstring sn = cstring_copy (f);
4295               
4296               DPRINTF (("Here: %s", exprNode_unparse (s)));
4297               
4298               exprNode_checkUse (ret, s->sref, s->loc);
4299               exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4300               
4301               cstring_markOwned (sn);
4302               ret->sref = sRef_makeArrow (s->sref, sn);
4303               
4304               ret->kind = XPR_ARROW;
4305               return (ret);
4306             }
4307         }
4308       
4309       return (ret);
4310     }
4311   BADEXIT;
4312 }
4313
4314 exprNode
4315 exprNode_arrowAccess (/*@only@*/ exprNode s, 
4316                       /*@only@*/ lltok arrow,
4317                       /*@only@*/ cstring f)
4318 {
4319   exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4320   lltok_release (arrow);
4321   return res;
4322 }
4323
4324 /*
4325 ** only postOp's in C: i++ and i--
4326 */
4327
4328 exprNode
4329 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4330 {
4331   /* check modification also */
4332   /* cstring opname = lltok_unparse (op);*/
4333   ctype t;
4334   exprNode ret = exprNode_createPartialCopy (e);
4335
4336   ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4337   ret->kind = XPR_POSTOP;
4338   ret->edata = exprData_makeUop (e, op);
4339
4340   if (!exprNode_isDefined (e))
4341     {
4342       return ret;
4343     }
4344
4345   checkMacroParen (e);
4346
4347   exprNode_checkUse (ret, e->sref, e->loc);
4348   exprNode_checkSet (ret, e->sref);
4349
4350   t = exprNode_getType (e);
4351
4352   if (sRef_isUnsafe (e->sref))
4353     {
4354       voptgenerror (FLG_MACROPARAMS,
4355                     message ("Operand of %s is macro parameter (non-functional): %s%s", 
4356                              lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4357                     e->loc);
4358       sRef_makeSafe (e->sref);
4359       sRef_makeSafe (ret->sref);
4360     }
4361
4362   if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4363     {
4364       ret->typ = e->typ;
4365     }
4366   else
4367     {
4368       if (ctype_isRealAbstract (t))
4369         {
4370           voptgenerror 
4371             (FLG_ABSTRACT,
4372              message ("Operand of %s is abstract type (%t): %s",
4373                       lltok_unparse (op), t, exprNode_unparse (e)),
4374              e->loc);
4375         }
4376       else
4377         {
4378           voptgenerror 
4379             (FLG_TYPE,
4380              message ("Operand of %s is non-numeric (%t): %s",
4381                       lltok_unparse (op), t, exprNode_unparse (e)),
4382              e->loc);
4383         }
4384       ret->typ = ctype_unknown;
4385     }
4386
4387   /* if (ctype_isZero (t)) e->typ = ctype_int; */
4388
4389   exprNode_checkModify (e, ret);
4390
4391   /* added 7/11/2000 D.L */
4392   /*@i223*/ 
4393   /*DRL 6/8/01 I decided to disable all Splint warnings here since the code 
4394     probably needs a rewrite any way */
4395
4396   /*@i65234@*/
4397   /*@ignore@*/
4398
4399   /* updateEnvironmentForPostOp (e); */
4400   
4401   /* start modifications */
4402   /* added by Seejo on 4/16/2000 */
4403   
4404   /* Arithmetic operations on pointers wil modify the size/len/null terminated 
4405      status */
4406   if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4407     
4408     ret->sref = sRef_copy (e->sref);
4409     
4410     /* Operator : ++ */
4411     if (lltok_getTok (op) == INC_OP) {
4412       if (sRef_getSize(e->sref) > 0) {
4413         
4414         sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4415         
4416         if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4417           /* Assumption: there is only 1 \0 in the buffer */
4418           /* This will not be correct if there are 2 \0's in the buffer */
4419           sRef_setNotNullTerminatedState(ret->sref);
4420           sRef_resetLen(ret->sref);
4421         } else {
4422           sRef_setNullTerminatedState(ret->sref);
4423           sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4424         }
4425         if (sRef_isNullTerminated (ret->sref))
4426           printf ("ret->sref is Null Terminated\n");
4427         else if (sRef_isPossiblyNullTerminated (ret->sref))
4428           printf ("ret->sref is Possibly Null Terminated\n");
4429         else if (sRef_isNotNullTerminated (ret->sref))
4430           printf ("ret->sref is Not Null Terminated\n");
4431       }
4432     }
4433     
4434     /* Operator : -- */
4435     if (lltok_getTok (op) == DEC_OP) {
4436       if (sRef_getSize(e->sref) >= 0) {
4437         sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4438         sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4439       }
4440     }
4441   }
4442   /*@end@*/
4443   /* end modifications */
4444
4445   return ret;
4446 }
4447
4448 exprNode
4449 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4450 {
4451   bool checkMod = FALSE;
4452   ctype te, tr;
4453   int opid = lltok_getTok (op);
4454   exprNode ret = exprNode_createSemiCopy (e);
4455
4456   exprNode_copySets (ret, e);
4457
4458   multiVal_free (ret->val);
4459   ret->val = multiVal_undefined;
4460   ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4461   ret->kind = XPR_PREOP;  
4462   ret->edata = exprData_makeUop (e, op);
4463   
4464   if (exprNode_isError (e))
4465     {
4466       return ret;
4467     }
4468   
4469   checkMacroParen (e);
4470   
4471   te = exprNode_getType (e);
4472   tr = ctype_realType (te);
4473   
4474   if (opid != TAMPERSAND)
4475     {
4476       exprNode_checkUse (ret, e->sref, e->loc);
4477       
4478       if (ctype_isRealAbstract (tr)
4479           && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4480         {
4481           if (optgenerror (FLG_ABSTRACT,
4482                            message ("Operand of %s is abstract type (%t): %s",
4483                                     lltok_unparse (op), tr,
4484                                     exprNode_unparse (ret)),
4485                            e->loc))
4486             {
4487               tr = te = ctype_unknown;
4488               ret->typ = ctype_unknown;
4489               sRef_setNullError (e->sref);
4490             }
4491         }
4492     }
4493   
4494   switch (opid)
4495     {
4496     case INC_OP:
4497     case DEC_OP:                /* should also check modification! */
4498       if (sRef_isMacroParamRef (e->sref))
4499         {
4500           voptgenerror 
4501             (FLG_MACROPARAMS,
4502              message ("Operand of %s is macro parameter (non-functional): %s", 
4503                       lltok_unparse (op), exprNode_unparse (ret)),
4504              e->loc);
4505         }
4506       else
4507         {
4508           exprNode_checkSet (ret, e->sref);
4509         }
4510       
4511       if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4512         {
4513         }
4514       else
4515         {
4516           if (context_msgStrictOps ())
4517             {
4518               voptgenerror 
4519                 (FLG_STRICTOPS,
4520                  message ("Operand of %s is non-numeric (%t): %s",
4521                           lltok_unparse (op), te, exprNode_unparse (ret)),
4522                  e->loc);
4523             }
4524           ret->typ = ctype_int;
4525         }
4526
4527         /* start modifications */
4528         /* added by Seejo on 4/16/2000 */
4529
4530         /* Arithmetic operations on pointers wil modify the size/len/null terminated 
4531                  status */
4532         if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4533
4534                 ret->sref = sRef_copy (e->sref);
4535
4536                 /* Operator : ++ */
4537                 if (lltok_getTok (op) == INC_OP) {
4538                         if (sRef_getSize(e->sref) > 0) {
4539
4540                                 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4541
4542                                 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4543                                         /* Assumption: there is only 1 \0 in the buffer */
4544                                         /* This will not be correct if there are 2 \0's in the buffer */
4545                                         sRef_setNotNullTerminatedState(ret->sref);
4546                                         sRef_resetLen (ret->sref);
4547                                 } else {
4548                                         sRef_setNullTerminatedState(ret->sref);
4549                                         sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4550                                 }
4551                         }
4552                 }
4553
4554                 /* Operator : -- */
4555                 if (lltok_getTok (op) == DEC_OP) {
4556                         if (sRef_getSize(e->sref) >= 0) {
4557                                 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4558                                 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4559                         }
4560                 }
4561         }
4562
4563         /* end modifications */    
4564
4565       checkMod = TRUE;
4566       break;
4567       
4568     case TMINUS:
4569     case TPLUS:
4570       if (ctype_isForceRealNumeric (&tr))
4571         {
4572           if (opid == TMINUS)
4573             {
4574               ret->val = multiVal_invert (exprNode_getValue (e));
4575             }
4576           else
4577             {
4578               ret->val = multiVal_copy (exprNode_getValue (e));
4579             }
4580         }
4581       else
4582         {
4583           if (context_msgStrictOps ())
4584             {
4585               voptgenerror 
4586                 (FLG_STRICTOPS,
4587                  message ("Operand of %s is non-numeric (%t): %s",
4588                           lltok_unparse (op), te, exprNode_unparse (ret)),
4589                  e->loc);
4590             }
4591
4592           ret->typ = ctype_int;
4593         }
4594       break;
4595       
4596     case TEXCL:         /* maybe this should be restricted */
4597       guardSet_flip (ret->guards);      
4598
4599       if (ctype_isRealBool (te) || ctype_isUnknown (te))
4600         {
4601          ;
4602         }
4603       else
4604         {
4605           if (ctype_isRealPointer (tr))
4606             {
4607               if (sRef_isKnown (e->sref))
4608                 {
4609                   ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4610                 }
4611               
4612               voptgenerror2n
4613                 (FLG_BOOLOPS, FLG_PTRNEGATE,
4614                  message ("Operand of %s is non-boolean (%t): %s",
4615                           lltok_unparse (op), te, exprNode_unparse (ret)),
4616                  e->loc);
4617             }
4618           else
4619             {
4620               voptgenerror
4621                 (FLG_BOOLOPS,
4622                  message ("Operand of %s is non-boolean (%t): %s",
4623                           lltok_unparse (op), te, exprNode_unparse (ret)),
4624                  e->loc);
4625             }
4626           
4627           ret->typ = ctype_bool;
4628         }
4629       break;
4630       
4631     case TTILDE:
4632       if (ctype_isForceRealInt (&tr))
4633         {
4634         }
4635       else
4636         {
4637           if (context_msgStrictOps ())
4638             {
4639               voptgenerror 
4640                 (FLG_STRICTOPS,
4641                  message ("Operand of %s is non-integer (%t): %s",
4642                           lltok_unparse (op), te, exprNode_unparse (ret)), 
4643                  e->loc);
4644             }
4645
4646           if (ctype_isInt (e->typ))
4647             {
4648               ret->typ = e->typ;
4649             }
4650           else
4651             {
4652               ret->typ = ctype_int;
4653             }
4654         }       
4655       break;
4656       
4657     case TAMPERSAND:
4658       ret->typ = ctype_makePointer (e->typ);
4659
4660       if (sRef_isKnown (e->sref))
4661         {
4662           ret->sref = sRef_makeAddress (e->sref);
4663         }
4664       
4665       break;
4666       
4667     case TMULT:
4668       
4669       if (ctype_isAP (tr))
4670         {
4671           ret->typ = ctype_baseArrayPtr (e->typ);
4672         }
4673       else
4674         {
4675           if (ctype_isKnown (te))
4676             {
4677               if (ctype_isFunction (te))
4678                 {
4679                   ret->typ = e->typ;
4680
4681                   voptgenerror
4682                     (FLG_FCNDEREF,
4683                      message ("Dereference of function type (%t): %s",
4684                               te, exprNode_unparse (ret)),
4685                      e->loc);
4686                 }
4687               else
4688                 {
4689                   voptgenerror (FLG_TYPE,
4690                                 message ("Dereference of non-pointer (%t): %s",
4691                                          te, exprNode_unparse (ret)),
4692                                 e->loc);
4693                   ret->typ = ctype_unknown;
4694                 }
4695             }
4696           else
4697             {
4698               ret->typ = ctype_unknown;
4699             }
4700           
4701         }
4702       
4703       if (sRef_isKnown (e->sref))
4704         {
4705           DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4706
4707           if (sRef_possiblyNull (e->sref))
4708             {
4709               DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4710               if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4711                 {
4712                   if (optgenerror 
4713                       (FLG_NULLDEREF,
4714                        message ("Dereference of %s pointer %q: %s", 
4715                                 sRef_nullMessage (e->sref),
4716                                 sRef_unparse (e->sref),
4717                                 exprNode_unparse (ret)),
4718                        e->loc))
4719                     {
4720                       sRef_showNullInfo (e->sref);
4721                       sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4722                     }
4723                 }
4724             }
4725           
4726           ret->sref = sRef_makePointer (e->sref);
4727         }
4728       break;
4729       
4730     default:
4731       llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4732     }
4733
4734   if (checkMod)
4735     {
4736       exprNode_checkModify (e, ret);
4737     }
4738
4739   return ret;
4740 }
4741
4742 /*
4743 ** any reason to disallow sizeof (abstract type) ?
4744 */
4745
4746 /*
4747 ** used by both sizeof
4748 */
4749
4750 static
4751 ctype sizeof_resultType (void)
4752 {
4753   static ctype sizet = ctype_unknown;
4754
4755   if (ctype_isUnknown (sizet))
4756     {
4757       if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4758         {
4759           sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4760         }
4761       else
4762         {
4763           sizet = ctype_ulint;
4764         }
4765     }
4766   return sizet;
4767 }
4768
4769 exprNode
4770 exprNode_sizeofType (/*@only@*/ qtype qt)
4771 {
4772   exprNode ret = exprNode_create (sizeof_resultType ());
4773   ctype ct = qtype_getType (qt);
4774
4775   ret->kind = XPR_SIZEOFT;
4776   ret->edata = exprData_makeSizeofType (qt);
4777
4778   voptgenerror (FLG_SIZEOFTYPE,
4779                 message ("Parameter to sizeof is type %s: %s",
4780                          ctype_unparse (ct),
4781                          exprNode_unparse (ret)),
4782                 ret->loc);
4783   
4784   return (ret);
4785 }
4786
4787 exprNode
4788 exprNode_alignofType (/*@only@*/ qtype qt)
4789 {
4790   exprNode ret = exprNode_create (sizeof_resultType ());
4791   ctype ct = qtype_getType (qt);
4792
4793   ret->kind = XPR_ALIGNOFT;
4794   ret->edata = exprData_makeSizeofType (qt);
4795
4796   voptgenerror (FLG_SIZEOFTYPE,
4797                 message ("Parameter to alignof is type %s: %s",
4798                          ctype_unparse (ct),
4799                          exprNode_unparse (ret)),
4800                 ret->loc);
4801   
4802   return (ret);
4803 }
4804
4805 exprNode exprNode_offsetof (qtype qt, cstringList s)
4806 {
4807   exprNode ret = exprNode_create (sizeof_resultType ());
4808   ctype ct = qtype_getType (qt);
4809
4810   ret->kind = XPR_OFFSETOF;
4811   ret->edata = exprData_makeOffsetof (qt, s);
4812
4813   if (!ctype_isRealSU (ct))
4814     {
4815       voptgenerror (FLG_TYPE,
4816                     message ("First parameter to offsetof is not a "
4817                              "struct or union type (type %s): %s",
4818                              ctype_unparse (ct),
4819                              exprNode_unparse (ret)),
4820                     ret->loc);
4821     }
4822   else
4823     {
4824       ctype lt = ct;
4825
4826       cstringList_elements (s, el) {
4827         uentryList fields;
4828         uentry fld;
4829
4830         if (ctype_isUndefined (lt))
4831           {
4832             break;
4833           } 
4834         else if (!ctype_isRealSU (lt))
4835           {
4836             voptgenerror (FLG_TYPE,
4837                           message ("Inner offsetof type is not a "
4838                                    "struct or union type (type %s before field %s): %s",
4839                                    ctype_unparse (lt), el,
4840                                    exprNode_unparse (ret)),
4841                           ret->loc);
4842             break;
4843           }
4844         else 
4845           {
4846             fields = ctype_getFields (ctype_realType (lt));
4847             fld = uentryList_lookupField (fields, el);
4848             DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4849             
4850             if (uentry_isUndefined (fld))
4851               {
4852                 if (ctype_equal (lt, ct)) {
4853                   voptgenerror (FLG_TYPE,
4854                                 message ("Field %s in offsetof is not the "
4855                                          "name of a field of %s: %s",
4856                                          el,
4857                                          ctype_unparse (ct),
4858                                          exprNode_unparse (ret)),
4859                                 ret->loc);
4860                 } else {
4861                   voptgenerror (FLG_TYPE,
4862                                 message ("Deep field %s in offsetof is not the "
4863                                          "name of a field of %s: %s",
4864                                          el,
4865                                          ctype_unparse (lt),
4866                                          exprNode_unparse (ret)),
4867                                 ret->loc);
4868                 }
4869               }
4870             else 
4871               {
4872                 lt = uentry_getType (fld);
4873               }
4874           }
4875       } end_cstringList_elements;
4876
4877       /* Should report error if its a bit field - behavior is undefined! */
4878     }
4879   
4880   return (ret);
4881 }
4882
4883 /*@only@*/ exprNode
4884 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4885 {
4886   exprNode ret;
4887
4888   if (exprNode_isUndefined (e))
4889     {
4890       ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4891       ret->edata = exprData_makeSingle (e);
4892       ret->typ = sizeof_resultType ();
4893       ret->kind = XPR_SIZEOF;
4894     }
4895   else
4896     {
4897       uentry u = exprNode_getUentry (e);
4898
4899       ret = exprNode_createPartialCopy (e);
4900       ret->edata = exprData_makeSingle (e);
4901
4902       ret->typ = sizeof_resultType ();
4903       ret->kind = XPR_SIZEOF;
4904
4905       if (uentry_isValid (u) 
4906           && uentry_isRefParam (u)
4907           && ctype_isRealArray (uentry_getType (u)))
4908         {
4909           voptgenerror
4910             (FLG_SIZEOFFORMALARRAY,
4911              message ("Parameter to sizeof is an array-type function parameter: %s",
4912                       exprNode_unparse (ret)),
4913              ret->loc);
4914         }
4915     }
4916
4917   /*
4918   ** sizeof (x) doesn't "really" use x
4919   */
4920
4921   return (ret);
4922 }
4923
4924 /*@only@*/ exprNode
4925 exprNode_alignofExpr (/*@only@*/ exprNode e)
4926 {
4927   exprNode ret;
4928
4929   if (exprNode_isUndefined (e))
4930     {
4931       ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4932     }
4933   else
4934     {
4935       ret = exprNode_createPartialCopy (e);
4936     }
4937
4938   ret->edata = exprData_makeSingle (e);
4939   ret->typ = sizeof_resultType ();
4940   ret->kind = XPR_ALIGNOF;
4941   
4942   /*
4943   ** sizeof (x) doesn't "really" use x
4944   */
4945
4946   return (ret);
4947 }
4948
4949 /*@only@*/ exprNode
4950 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4951 {
4952   ctype c;
4953   ctype t;
4954   exprNode ret;
4955
4956   if (exprNode_isError (e))
4957     {
4958       qtype_free (q);
4959       lltok_release (tok);
4960       return exprNode_undefined;
4961     }
4962
4963   checkMacroParen (e);
4964
4965   c = qtype_getType (q);
4966   t = exprNode_getType (e);
4967
4968   ret = exprNode_createPartialCopy (e);
4969   
4970   ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4971   ret->typ = c;
4972   ret->kind = XPR_CAST;
4973   ret->edata = exprData_makeCast (tok, e, q);
4974
4975   if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4976     {
4977       /* 
4978       ** This is a bit of a hack to avoid a problem
4979       ** when the code does,
4980       **          (some other struct) x
4981       **          ...
4982       **          x->field
4983       */
4984
4985       ret->sref = sRef_copy (e->sref);
4986       usymtab_addForceMustAlias (ret->sref, e->sref);
4987       sRef_setTypeFull (ret->sref, c);
4988       DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4989                 sRef_unparseFull (ret->sref)));
4990     }
4991   else
4992     {
4993       ret->sref = e->sref;
4994       sRef_setTypeFull (ret->sref, c);
4995       DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4996     }
4997
4998   /*
4999   ** we allow
5000   **       abstract  -> void
5001   **              0 <-> abstract * 
5002   **         void * <-> abstract *  (if FLG_ABSTVOIDP)
5003   **     abstract * <-> void *      (if FLG_ABSTVOIDP)
5004   */
5005
5006   if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
5007     {
5008       ;
5009     }
5010   else if (ctype_isRealAP (c)) /* casting to array or pointer */
5011     {
5012       ctype bc = ctype_getBaseType (c);
5013       ctype bt = ctype_getBaseType (t);
5014       ctype rt = ctype_realType (t);
5015
5016       if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
5017           && (ctype_isArrayPtr (rt)
5018               && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5019         {
5020           voptgenerror
5021             (FLG_CASTFCNPTR,
5022              message ("Cast from function pointer type (%t) to "
5023                       "non-function pointer (%t): %s",
5024                       c, t, exprNode_unparse (ret)),
5025              e->loc);     
5026         }
5027
5028       if (!ctype_isFunction (ctype_baseArrayPtr (c))
5029           && (ctype_isArrayPtr (rt)
5030               && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5031         {
5032           voptgenerror
5033             (FLG_CASTFCNPTR,
5034              message ("Cast from non-function pointer type (%t) to "
5035                       "function pointer (%t): %s",
5036                       c, t, exprNode_unparse (ret)),
5037              e->loc);     
5038         }
5039
5040       if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5041           !(ctype_isRealAbstract (bc)
5042             && context_hasAccess (ctype_typeId (bc))))
5043         {
5044          ; /* okay to cast zero */
5045         }
5046       else
5047         {
5048           if (ctype_isRealAbstract (bc)
5049               && !context_hasAccess (ctype_typeId (bc)))
5050             {
5051               if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5052                 {
5053                   vnoptgenerror
5054                     (FLG_ABSTVOIDP,
5055                      message ("Cast to underlying abstract type %t: %s",
5056                               c, exprNode_unparse (ret)),
5057                      e->loc);
5058                 }
5059               else
5060                 {
5061                   voptgenerror
5062                     (FLG_ABSTRACT,
5063                      message ("Cast to underlying abstract type %t: %s",
5064                               c, exprNode_unparse (ret)),
5065                      e->loc);     
5066                 }
5067             }
5068
5069           if (ctype_isRealAbstract (bt)
5070               && !context_hasAccess (ctype_typeId (bt)))
5071             {
5072               if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5073                 {
5074                   vnoptgenerror
5075                     (FLG_ABSTVOIDP,
5076                      message ("Cast from underlying abstract type %t: %s",
5077                               t, exprNode_unparse (ret)),
5078                      e->loc);
5079                 }
5080               else
5081                 {
5082                   voptgenerror
5083                     (FLG_ABSTRACT,
5084                      message ("Cast from underlying abstract type %t: %s",
5085                               t, exprNode_unparse (ret)),
5086                      e->loc);
5087                 }
5088             }
5089         }
5090     }
5091   else
5092     {
5093       ctype bt = ctype_realType (ctype_getBaseType (t));
5094       ctype bc = ctype_realType (ctype_getBaseType (c));
5095
5096       if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5097         {
5098           if (ctype_match (c, t))
5099             {
5100               if (ctype_equal (c, t))
5101                 {
5102                   voptgenerror
5103                     (FLG_TYPE, 
5104                      message ("Redundant cast involving abstract type %t: %s",
5105                               bt, exprNode_unparse (ret)),
5106                      e->loc);
5107                 }
5108             }
5109           else
5110             {
5111               voptgenerror
5112                 (FLG_ABSTRACT,
5113                  message ("Cast from abstract type %t: %s", 
5114                           bt, exprNode_unparse (ret)),
5115                  e->loc);
5116             }
5117         }
5118       
5119       if (ctype_isAbstract (bc) 
5120           && !context_hasAccess (ctype_typeId (bc)))
5121         {
5122           if (ctype_match (c, t))
5123             {
5124              ;
5125             }
5126           else
5127             {
5128               DPRINTF (("No access to: %s / %d",
5129                         ctype_unparse (bc), ctype_typeId (bc)));
5130               DPRINTF (("Context %s %s",
5131                         bool_unparse (context_inFunctionLike ()),
5132                         context_unparse ()));
5133               voptgenerror 
5134                 (FLG_ABSTRACT,
5135                  message ("Cast to abstract type %t: %s", bc, 
5136                           exprNode_unparse (ret)),
5137                  e->loc);
5138             }
5139         }
5140     }
5141
5142   if (ctype_isAbstract (c))
5143     {
5144       if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5145         {
5146           /* okay, cast exposed to abstract */
5147           sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5148         }
5149       else 
5150         {
5151           if (ctype_isVisiblySharable (t) 
5152               && sRef_isExternallyVisible (e->sref)
5153               && !(ctype_isAbstract (t) 
5154                    && context_hasAccess (ctype_typeId (t))))
5155             {
5156               voptgenerror 
5157                 (FLG_CASTEXPOSE,
5158                  message ("Cast to abstract type from externally visible "
5159                           "mutable storage exposes rep of %s: %s",
5160                           ctype_unparse (c),
5161                           exprNode_unparse (e)),
5162                  e->loc);
5163             }
5164         }
5165     }
5166
5167   return (ret);
5168 }
5169
5170 static bool
5171 evaluationOrderUndefined (lltok op)
5172 {
5173   int opid = lltok_getTok (op);
5174
5175   return (opid != AND_OP && opid != OR_OP);
5176 }
5177
5178 static bool checkIntegral (/*@notnull@*/ exprNode e1, 
5179                            /*@notnull@*/ exprNode e2, 
5180                            /*@notnull@*/ exprNode ret, 
5181                            lltok op)
5182 {
5183   bool error = FALSE;
5184
5185   ctype te1 = exprNode_getType (e1);
5186   ctype te2 = exprNode_getType (e2);
5187
5188   ctype tr1 = ctype_realishType (te1);
5189   ctype tr2 = ctype_realishType (te2);
5190   
5191   if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5192     {
5193       ;
5194     }
5195   else
5196     {
5197       if (context_msgStrictOps ())
5198         {
5199           if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5200             {
5201               if (ctype_sameName (te1, te2))
5202                 {
5203                   error = optgenerror 
5204                     (FLG_STRICTOPS,
5205                      message ("Operands of %s are non-integer (%t): %s",
5206                               lltok_unparse (op), te1,
5207                               exprNode_unparse (ret)),
5208                      e1->loc);
5209                 }
5210               else
5211                 {
5212                   error = optgenerror 
5213                     (FLG_STRICTOPS,
5214                      message ("Operands of %s are non-integers (%t, %t): %s",
5215                               lltok_unparse (op), te1, te2,
5216                               exprNode_unparse (ret)),
5217                      e1->loc);
5218                 }
5219             }
5220           else if (!ctype_isInt (tr1))
5221             {
5222               error = optgenerror 
5223                 (FLG_STRICTOPS,
5224                  message ("Left operand of %s is non-integer (%t): %s",
5225                           lltok_unparse (op), te1, exprNode_unparse (ret)),
5226                  e1->loc);
5227             }
5228           else
5229             /* !ctype_isInt (te2) */
5230             {
5231               error = optgenerror 
5232                 (FLG_STRICTOPS,
5233                  message ("Right operand of %s is non-integer (%t): %s",
5234                           lltok_unparse (op), te2, exprNode_unparse (ret)),
5235                  e2->loc);
5236             }
5237         }
5238     }
5239
5240   return !error;
5241 }
5242
5243 /*
5244 ** returns exprNode representing e1 op e2
5245 **
5246 ** uses msg if there are errors
5247 ** can be used for both assignment ops and regular ops
5248 **
5249 ** modifies e1
5250 */
5251
5252 static /*@only@*/ /*@notnull@*/ exprNode
5253 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2, 
5254                  /*@keep@*/ lltok op)
5255 {
5256   ctype te1, te2, tr1, tr2, tret;
5257   int opid = lltok_getTok (op);
5258   bool hasError = FALSE;
5259   exprNode ret;
5260
5261   if (exprNode_isError (e1))
5262     {
5263       ret = exprNode_createPartialNVCopy (e2);
5264     }
5265   else
5266     {
5267       ret = exprNode_createPartialNVCopy (e1);    
5268     }
5269
5270   ret->val = multiVal_undefined;
5271
5272   ret->kind = XPR_OP;
5273   ret->edata = exprData_makeOp (e1, e2, op);
5274
5275   if (exprNode_isError (e1) || exprNode_isError (e2))
5276     {
5277       if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5278           || opid == EQ_OP || opid == NE_OP 
5279           || opid == AND_OP || opid == OR_OP)
5280         {
5281           ret->typ = ctype_bool;
5282         }
5283
5284       if (exprNode_isDefined (e1))
5285         {
5286           exprNode_checkUse (ret, e1->sref, e1->loc);  
5287         }
5288
5289       if (exprNode_isDefined (e2))
5290         {
5291           exprNode_mergeUSs (ret, e2);
5292           exprNode_checkUse (ret, e2->sref, e2->loc);  
5293         }
5294
5295       return ret;
5296     }
5297
5298   tret = ctype_unknown;
5299   te1 = exprNode_getType (e1);
5300
5301   DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5302
5303   te2 = exprNode_getType (e2);
5304
5305   tr1 = ctype_realishType (te1);
5306   tr2 = ctype_realishType (te2);
5307
5308   if (opid == OR_OP)
5309     {
5310       ret->guards = guardSet_or (ret->guards, e2->guards);
5311     }
5312   else if (opid == AND_OP)
5313     {
5314       ret->guards = guardSet_and (ret->guards, e2->guards);
5315     }
5316   else
5317     {
5318       /* no guards */
5319     }
5320
5321   if (opid == EQ_OP || opid == NE_OP)
5322     {
5323       exprNode temp1 = e1, temp2 = e2;
5324
5325       /* could do NULL == x */
5326       
5327       if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5328         {
5329           temp1 = e2; temp2 = e1;
5330         }
5331
5332       if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5333         {
5334           reflectNullTest (temp1, (opid == NE_OP));
5335           guardSet_free (ret->guards);
5336           ret->guards = guardSet_copy (temp1->guards);
5337         }
5338     }
5339
5340   if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5341       || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5342     {
5343       tret = ctype_bool; 
5344     }
5345   
5346   if (anyAbstract (tr1, tr2) &&
5347       (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) && 
5348          (opid == AND_OP || opid == OR_OP 
5349           || opid == EQ_OP || opid == NE_OP))))
5350     {
5351       abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5352     }
5353   else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5354     {
5355       /* unknown types, no comparisons possible */
5356     }
5357   else
5358     {
5359       switch (opid)
5360         {
5361         case TMULT:             /* multiplication and division:           */
5362         case TDIV:              /*                                        */
5363         case MUL_ASSIGN:        /*    numeric, numeric -> numeric         */
5364         case DIV_ASSIGN:        /*                                        */
5365
5366           if (opid == TMULT || opid == MUL_ASSIGN)
5367             {
5368               ret->val = multiVal_multiply (exprNode_getValue (e1),
5369                                             exprNode_getValue (e2));
5370             }
5371           else
5372             {
5373               ret->val = multiVal_divide (exprNode_getValue (e1),
5374                                           exprNode_getValue (e2));
5375             }
5376                   
5377           tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5378           break;
5379           
5380         case TPLUS:             /* addition and subtraction:               */
5381         case TMINUS:            /*    pointer, int     -> pointer          */
5382         case SUB_ASSIGN:        /*    int, pointer     -> pointer          */
5383         case ADD_ASSIGN:        /*    numeric, numeric -> numeric          */
5384
5385           if (opid == TPLUS || opid == ADD_ASSIGN)
5386             {
5387               ret->val = multiVal_add (exprNode_getValue (e1),
5388                                        exprNode_getValue (e2));
5389             }
5390           else
5391             {
5392               ret->val = multiVal_subtract (exprNode_getValue (e1),
5393                                             exprNode_getValue (e2));
5394             }
5395
5396           tr1 = ctype_fixArrayPtr (tr1);
5397
5398           if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5399               && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5400             {
5401               /* pointer + int */
5402
5403               if (context_msgPointerArith ())
5404                 {
5405                   voptgenerror
5406                     (FLG_POINTERARITH,
5407                      message ("Pointer arithmetic (%t, %t): %s", 
5408                               te1, te2, exprNode_unparse (ret)),
5409                      e1->loc);
5410                 }
5411
5412               /*
5413               ** Swap terms so e1 is always the pointer
5414               */
5415
5416               if (ctype_isRealPointer (tr1))
5417                 {
5418                   ;
5419                 }
5420               else
5421                 {
5422                   exprNode_swap (e1, e2);
5423                 }
5424
5425
5426               if (sRef_possiblyNull (e1->sref)
5427                   && !usymtab_isGuarded (e1->sref))
5428                 {
5429                   voptgenerror
5430                     (FLG_NULLPOINTERARITH,
5431                      message ("Pointer arithmetic involving possibly "
5432                               "null pointer %s: %s", 
5433                               exprNode_unparse (e1), 
5434                               exprNode_unparse (ret)),
5435                      e1->loc);
5436                 }
5437
5438               ret->sref = sRef_copy (e1->sref);
5439
5440               /* start modifications */
5441               /* added by Seejo on 4/16/2000 */
5442
5443               /* Arithmetic operations on pointers wil modify the size/len/null terminated 
5444                  status */
5445               if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5446                 int val;
5447                 /*drl 1-4-2002
5448                   added ugly fixed to stop
5449                   program from crashing on point + int +int
5450                   one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5451                 
5452                 if (!multiVal_isInt (e2->val) )
5453                   break;
5454                 /*end drl*/
5455                 
5456                 val = (int) multiVal_forceInt (e2->val);
5457                 
5458                 /* Operator : + or += */
5459                 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5460                   if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by 
5461                                                          val should not result in a 
5462                                                          size < 0 (size = 0 is ok !) */
5463                     
5464                     sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5465                     
5466                     if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5467                       sRef_setNotNullTerminatedState(ret->sref);
5468                       sRef_resetLen (ret->sref);
5469                     } else {
5470                       sRef_setNullTerminatedState(ret->sref);
5471                       sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5472                     }
5473                   }
5474                 }
5475                 
5476                 /* Operator : - or -= */
5477                 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5478                   if (sRef_getSize(e1->sref) >= 0) {
5479                     sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5480                     sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5481                   }
5482                 }
5483               }
5484               
5485               /* end modifications */  
5486
5487               sRef_setNullError (ret->sref);
5488
5489               /*
5490               ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5491               ** since is points to storage that should not be deallocated
5492               ** through this pointer.
5493               */
5494
5495               if (sRef_isOnly (ret->sref) 
5496                   || sRef_isFresh (ret->sref)) 
5497                 {
5498                   sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5499                 }
5500               
5501               tret = e1->typ;
5502             }
5503           else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1)) 
5504                    && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5505             {
5506               if (context_msgPointerArith ())
5507                 {
5508                   voptgenerror 
5509                     (FLG_POINTERARITH,
5510                      message ("Pointer arithmetic (%t, %t): %s", 
5511                               te1, te2, exprNode_unparse (ret)),
5512                      e1->loc);
5513                 }
5514
5515               if (sRef_possiblyNull (e1->sref)
5516                   && !usymtab_isGuarded (e1->sref))
5517                 {
5518                   voptgenerror
5519                     (FLG_NULLPOINTERARITH,
5520                      message ("Pointer arithmetic involving possibly "
5521                               "null pointer %s: %s", 
5522                               exprNode_unparse (e2), 
5523                               exprNode_unparse (ret)),
5524                      e2->loc);
5525                 }
5526
5527               ret->sref = sRef_copy (e2->sref);
5528
5529               /* start modifications */
5530               /* added by Seejo on 4/16/2000 */
5531               
5532               /* Arithmetic operations on pointers wil modify the size/len/null terminated 
5533                  status */
5534               
5535               if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5536                 int val = (int) multiVal_forceInt (e1->val);
5537                 
5538                 /* Operator : + or += */
5539                 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5540                   if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by 
5541                                                          val should not result in a 
5542                                                          size < 0 (size = 0 is ok !) */
5543                     
5544                     sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5545                     
5546                     if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5547                       sRef_setNotNullTerminatedState(ret->sref);
5548                       sRef_resetLen (ret->sref);
5549                     } else {
5550                       sRef_setNullTerminatedState(ret->sref);
5551                       sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5552                     }
5553                   }
5554                 }
5555                 
5556                 /* Operator : - or -= */
5557                 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5558                   if (sRef_getSize(e2->sref) >= 0) {
5559                     sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5560                     sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5561                   }
5562                 }
5563               }
5564               /* end modifications */
5565               
5566               sRef_setNullError (ret->sref);
5567               
5568               /*
5569               ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5570               ** since is points to storage that should not be deallocated
5571               ** through this pointer.
5572               */
5573               
5574               if (sRef_isOnly (ret->sref) 
5575                   || sRef_isFresh (ret->sref)) {
5576                 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5577               }
5578               
5579               tret = e2->typ;
5580               ret->sref = e2->sref;
5581             }
5582           else
5583             {
5584               tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5585             }
5586           
5587           break;
5588
5589         case LEFT_ASSIGN:   
5590         case RIGHT_ASSIGN:
5591         case LEFT_OP:
5592         case RIGHT_OP:
5593         case TAMPERSAND:    /* bitwise & */
5594         case AND_ASSIGN:       
5595         case TCIRC:         /* ^ (XOR) */
5596         case TBAR:
5597         case XOR_ASSIGN:
5598         case OR_ASSIGN:
5599           {
5600             bool reported = FALSE;
5601             
5602             /*
5603             ** Shift Operator 
5604             */
5605
5606             if (opid == LEFT_OP || opid == LEFT_ASSIGN
5607                 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) 
5608               {
5609                 /*
5610                 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5611                 */
5612                 
5613                 if (!ctype_isUnsigned (tr2)
5614                     && !exprNode_isNonNegative (e2))
5615                   {
5616                     reported = optgenerror 
5617                       (FLG_SHIFTNEGATIVE,
5618                        message ("Right operand of %s may be negative (%t): %s",
5619                                 lltok_unparse (op), te2,
5620                                 exprNode_unparse (ret)),
5621                        e2->loc);
5622                   }
5623                 
5624                 if (!ctype_isUnsigned (tr1)
5625                     && !exprNode_isNonNegative (e1))
5626                   {
5627                     reported = optgenerror 
5628                       (FLG_SHIFTIMPLEMENTATION,
5629                        message ("Left operand of %s may be negative (%t): %s",
5630                                 lltok_unparse (op), te1,
5631                                 exprNode_unparse (ret)),
5632                        e1->loc);
5633                   }
5634                 
5635                 /*
5636                 ** Should check size of right operand also...
5637                 */
5638                 
5639               }
5640             else
5641               {
5642                 if (!ctype_isUnsigned (tr1)) 
5643                   {
5644                     if (exprNode_isNonNegative (e1)) {
5645                       ;
5646                     } else {
5647                       reported = optgenerror 
5648                         (FLG_BITWISEOPS,
5649                          message ("Left operand of %s is not unsigned value (%t): %s",
5650                                   lltok_unparse (op), te1,
5651                                   exprNode_unparse (ret)),
5652                          e1->loc);
5653                       
5654                       if (reported) {
5655                         te1 = ctype_uint;
5656                       }
5657                     }
5658                   }
5659                 else 
5660                   {
5661                     if (!ctype_isUnsigned (tr2)) 
5662                       {
5663                         if (!exprNode_isNonNegative (e2)) {
5664                           reported = optgenerror 
5665                             (FLG_BITWISEOPS,
5666                              message ("Right operand of %s is not unsigned value (%t): %s",
5667                                       lltok_unparse (op), te2,
5668                                       exprNode_unparse (ret)),
5669                              e2->loc);
5670                         }
5671                       }
5672                   }
5673               }
5674
5675             if (!reported) 
5676               {
5677                 if (!checkIntegral (e1, e2, ret, op)) {
5678                   te1 = ctype_unknown;
5679                 }
5680               }
5681             
5682             DPRINTF (("Set: %s", ctype_unparse (te1)));     
5683
5684             /*
5685             ** tret is the widest type of te1 and te2 
5686             */
5687
5688             tret = ctype_widest (te1, te2);
5689             break;
5690           }
5691         case MOD_ASSIGN:
5692         case TPERCENT:          
5693           if (checkIntegral (e1, e2, ret, op)) {
5694             tret = te1;
5695           } else {
5696             tret = ctype_unknown;
5697           }
5698           break;
5699         case EQ_OP: 
5700         case NE_OP:
5701         case TLT:               /* comparisons                           */
5702         case TGT:               /*    numeric, numeric -> bool           */
5703
5704           DPRINTF (("Here we go: %s / %s",
5705                     ctype_unparse (tr1), ctype_unparse (tr2)));
5706
5707           if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5708               || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5709             {
5710               ctype rtype = tr1;
5711               bool fepsilon = FALSE;
5712
5713               if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5714                 {
5715                   rtype = tr2;
5716                 }
5717               
5718               if (opid == TLT || opid == TGT)
5719                 {
5720                   uentry ue1 = exprNode_getUentry (e1);
5721                   uentry ue2 = exprNode_getUentry (e2);
5722
5723                   /*
5724                   ** FLT_EPSILON, etc. really is a variable, not
5725                   ** a constant.
5726                   */
5727
5728                   if (uentry_isVariable (ue1))
5729                     {
5730                       cstring uname = uentry_rawName (ue1);
5731
5732                       if (cstring_equalLit (uname, "FLT_EPSILON")
5733                           || cstring_equalLit (uname, "DBL_EPSILON")
5734                           || cstring_equalLit (uname, "LDBL_EPSILON"))
5735                         {
5736                           fepsilon = TRUE;
5737                         }
5738                     }
5739
5740                   if (uentry_isVariable (ue2))
5741                     {
5742                       cstring uname = uentry_rawName (ue2);
5743
5744                       if (cstring_equalLit (uname, "FLT_EPSILON")
5745                           || cstring_equalLit (uname, "DBL_EPSILON")
5746                           || cstring_equalLit (uname, "LDBL_EPSILON"))
5747                         {
5748                           fepsilon = TRUE;
5749                         }
5750                     }
5751                 }
5752
5753               if (fepsilon)
5754                 {
5755                   ; /* Don't complain. */
5756                 }
5757               else
5758                 {
5759                   voptgenerror
5760                     (FLG_REALCOMPARE,
5761                      message ("Dangerous comparison involving %s types: %s",
5762                               ctype_unparse (rtype),
5763                               exprNode_unparse (ret)),
5764                      ret->loc);
5765                 }
5766             }
5767           /*@fallthrough@*/
5768         case LE_OP:
5769         case GE_OP:
5770
5771           /*
5772           ** Types should match.
5773           */
5774
5775           DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5776                     exprNode_unparse (e2)));
5777
5778           if (!exprNode_matchTypes (e1, e2))
5779             {
5780               hasError = gentypeerror 
5781                 (te1, e1, te2, e2,
5782                  message ("Operands of %s have incompatible types (%t, %t): %s",
5783                           lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5784                  e1->loc);
5785               
5786             }
5787
5788           if (hasError 
5789               || (ctype_isForceRealNumeric (&tr1)
5790                   && ctype_isForceRealNumeric (&tr2)) ||
5791               (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5792             {
5793               ; /* okay */
5794             }
5795           else
5796             {
5797               if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5798                   (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5799                 {
5800                   voptgenerror 
5801                     (FLG_PTRNUMCOMPARE,
5802                      message ("Comparison of pointer and numeric (%t, %t): %s",
5803                               te1, te2, exprNode_unparse (ret)),
5804                      e1->loc);
5805                 }
5806               else
5807                 {
5808                   (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5809                 }
5810               tret = ctype_bool;
5811             }
5812
5813           /* certain comparisons on unsigned's and zero look suspicious */
5814
5815           if (opid == TLT || opid == LE_OP || opid == GE_OP)
5816             {
5817               if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5818                   || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5819                 {
5820                   voptgenerror 
5821                     (FLG_UNSIGNEDCOMPARE,
5822                      message ("Comparison of unsigned value involving zero: %s",
5823                               exprNode_unparse (ret)),
5824                      e1->loc);
5825                 }
5826             }
5827
5828           /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5829           
5830           if ((opid == EQ_OP || opid == NE_OP) && 
5831               ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5832             {
5833               /*
5834               ** is one a variable?
5835               */
5836
5837               if (uentry_isVariable (exprNode_getUentry (e1))
5838                   || uentry_isVariable (exprNode_getUentry (e2)))
5839                 {
5840                   /*
5841                   ** comparisons with FALSE are okay
5842                   */
5843
5844                   if (exprNode_isFalseConstant (e1)
5845                       || exprNode_isFalseConstant (e2))
5846                     {
5847                       ;
5848                     }
5849                   else
5850                     {
5851                       voptgenerror
5852                         (FLG_BOOLCOMPARE,
5853                          message 
5854                          ("Use of %q with %s variables (risks inconsistency because "
5855                           "of multiple true values): %s",
5856                           cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5857                           context_printBoolName (), exprNode_unparse (ret)),
5858                          e1->loc);
5859                     }
5860                 }
5861             }
5862           break;
5863           
5864         case AND_OP:            /* bool, bool -> bool */
5865         case OR_OP:
5866
5867           if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5868             {
5869               ; 
5870             }
5871           else
5872             {
5873               if (context_maybeSet (FLG_BOOLOPS))
5874                 {
5875                   if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5876                     {
5877                       if (ctype_sameName (te1, te2))
5878                         {
5879                           voptgenerror 
5880                             (FLG_BOOLOPS,
5881                              message ("Operands of %s are non-boolean (%t): %s",
5882                                       lltok_unparse (op), te1,
5883                                       exprNode_unparse (ret)),
5884                              e1->loc);
5885                         }
5886                       else
5887                         {
5888                           voptgenerror 
5889                             (FLG_BOOLOPS,
5890                              message
5891                              ("Operands of %s are non-booleans (%t, %t): %s",
5892                               lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5893                              e1->loc);
5894                         }
5895                     }
5896                   else if (!ctype_isRealBool (te1))
5897                     {
5898                       voptgenerror 
5899                         (FLG_BOOLOPS,
5900                          message ("Left operand of %s is non-boolean (%t): %s",
5901                                   lltok_unparse (op), te1, exprNode_unparse (ret)),
5902                          e1->loc);
5903                     }
5904                   else if (!ctype_isRealBool (te2))
5905                     {
5906                       voptgenerror
5907                         (FLG_BOOLOPS,
5908                          message ("Right operand of %s is non-boolean (%t): %s",
5909                                   lltok_unparse (op), te2, exprNode_unparse (ret)),
5910                          e2->loc);
5911                     }
5912                   else
5913                     {
5914                       ;
5915                     }
5916                 }
5917               tret = ctype_bool;
5918             }
5919           break;
5920         default: {
5921             llfatalbug 
5922               (cstring_makeLiteral 
5923                ("There has been a problem in the parser. This is believed to result "
5924                 "from a problem with bison v. 1.25.  Please try rebuidling Splint "
5925                 "using the pre-compiled grammar files by commenting out the "
5926                 "BISON= line in the top-level Makefile."));
5927           }
5928         }
5929     }
5930
5931   DPRINTF (("Return type: %s", ctype_unparse (tret)));
5932   ret->typ = tret;
5933
5934   exprNode_checkUse (ret, e1->sref, e1->loc);  
5935   exprNode_mergeUSs (ret, e2);
5936   exprNode_checkUse (ret, e2->sref, e2->loc);  
5937
5938   return ret;
5939 }
5940
5941 /*@only@*/ exprNode
5942 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5943              /*@only@*/ lltok op)
5944 {
5945   exprNode ret;
5946
5947   checkMacroParen (e1);
5948   checkMacroParen (e2);
5949
5950   if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5951     {
5952       checkExpressionDefined (e1, e2, op);
5953     }
5954
5955   ret = exprNode_makeOp (e1, e2, op);
5956   return (ret);
5957 }
5958
5959 static
5960 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5961 {
5962   /*
5963   ** This is somewhat bogus!
5964   **
5965   ** Assigning to a nested observer in a non-observer datatype
5966   ** should not produce an error.
5967   */
5968
5969   sRef ref = exprNode_getSref (e1);
5970
5971   DPRINTF (("Check assign mod: %s",
5972             sRef_unparseFull (ref)));
5973
5974   if (sRef_isObserver (ref) 
5975       || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5976           && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5977     {
5978       sRef base = sRef_getBase (ref);
5979
5980       if (sRef_isValid (base) && sRef_isObserver (base))
5981         {
5982           exprNode_checkModify (e1, ret);
5983         }
5984       else
5985         {
5986           exprNode_checkModifyVal (e1, ret);
5987         }
5988     }
5989   else
5990     {
5991       exprNode_checkModify (e1, ret);
5992     }
5993 }
5994
5995 exprNode
5996 exprNode_assign (/*@only@*/ exprNode e1,
5997                  /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5998 {
5999   bool isalloc = FALSE;
6000   bool isjustalloc = FALSE;
6001   bool noalias = FALSE;
6002   exprNode ret;
6003
6004   DPRINTF (("%s [%s] <- %s [%s]",
6005             exprNode_unparse (e1),
6006             ctype_unparse (e1->typ),
6007             exprNode_unparse (e2),
6008             ctype_unparse (e2->typ)));
6009
6010   if (lltok_getTok (op) != TASSIGN) 
6011     {
6012       ret = exprNode_makeOp (e1, e2, op);
6013
6014       DPRINTF (("Here goes: %s %s",
6015                 ctype_unparse (e1->typ),
6016                 ctype_unparse (e2->typ)));
6017
6018       if (ctype_isNumeric (e2->typ)
6019           || ctype_isNumeric (e1->typ))
6020         {
6021           /* Its a pointer arithmetic expression like ptr += i */
6022           noalias = TRUE;
6023         }
6024     } 
6025   else 
6026     {
6027       ret = exprNode_createPartialCopy (e1);
6028       ret->kind = XPR_ASSIGN;
6029       ret->edata = exprData_makeOp (e1, e2, op);
6030
6031       if (!exprNode_isError (e2)) 
6032         {
6033           ret->sets = sRefSet_union (ret->sets, e2->sets);
6034           ret->msets = sRefSet_union (ret->msets, e2->msets);
6035           ret->uses = sRefSet_union (ret->uses, e2->uses);
6036         }
6037     }
6038
6039   checkExpressionDefined (e1, e2, op);
6040
6041   if (exprNode_isError (e1))
6042     {
6043       if (!exprNode_isError (e2)) 
6044         {
6045           ret->loc = fileloc_update (ret->loc, e2->loc);
6046         }
6047       else
6048         {
6049           ret->loc = fileloc_update (ret->loc, g_currentloc);
6050         }
6051     }
6052
6053   if (!exprNode_isError (e2))
6054     {
6055       checkMacroParen (e2);
6056     }
6057
6058   if (exprNode_isDefined (e1))
6059     {
6060       if (sRef_isMacroParamRef (e1->sref))
6061         {
6062           if (context_inIterDef ())
6063             {
6064               uentry ue = sRef_getUentry (e1->sref);
6065               
6066               if (uentry_isYield (ue))
6067                 {
6068                   ;
6069                 }
6070               else
6071                 {
6072                   if (fileloc_isDefined (e1->loc))
6073                     {
6074                       voptgenerror
6075                         (FLG_MACROPARAMS,
6076                          message ("Assignment to non-yield iter parameter: %q", 
6077                                   sRef_unparse (e1->sref)),
6078                          e1->loc);
6079                     }
6080                   else
6081                     {
6082                       voptgenerror 
6083                         (FLG_MACROPARAMS,
6084                          message ("Assignment to non-yield iter parameter: %q", 
6085                                   sRef_unparse (e1->sref)),
6086                          g_currentloc);
6087                     }
6088                 }
6089             }
6090           else
6091             {
6092               if (fileloc_isDefined (e1->loc))
6093                 {
6094                   voptgenerror
6095                     (FLG_MACROASSIGN,
6096                      message ("Assignment to macro parameter: %q", 
6097                               sRef_unparse (e1->sref)),
6098                      e1->loc);
6099                 }
6100               else
6101                 {
6102                   voptgenerror 
6103                     (FLG_MACROASSIGN,
6104                      message ("Assignment to macro parameter: %q", 
6105                               sRef_unparse (e1->sref)),
6106                      g_currentloc);
6107                 }
6108
6109               exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6110             }
6111         }
6112       else
6113         {
6114           exprNode_checkAssignMod (e1, ret);
6115         }
6116
6117       if (exprNode_isDefined (e2))
6118         {
6119           if (lltok_getTok (op) == TASSIGN) 
6120             {
6121               ctype te1 = exprNode_getType (e1);
6122               ctype te2 = exprNode_getType (e2);
6123               
6124               if (!ctype_forceMatch (te1, te2))
6125                 {
6126                   if (exprNode_matchLiteral (te1, e2))
6127                     {
6128                       ;
6129                     }
6130                   else
6131                     {
6132                       (void) gentypeerror 
6133                         (te2, e2, te1, e1,
6134                          message ("Assignment of %t to %t: %s %s %s", 
6135                                   te2, te1, exprNode_unparse (e1),
6136                                   lltok_unparse (op), 
6137                                   exprNode_unparse (e2)),
6138                          e1->loc);
6139                     }
6140                 }
6141             }
6142          
6143           exprNode_mergeUSs (ret, e2);
6144           exprNode_checkUse (ret, e2->sref, e2->loc);
6145           
6146           DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6147           if (noalias)
6148             {
6149               ;
6150             }
6151           else
6152             {
6153               doAssign (e1, e2, FALSE); 
6154             }
6155
6156           ret->sref = e1->sref;
6157         }
6158       else
6159         {
6160           if (exprNode_isDefined (e2))
6161             {
6162               exprNode_mergeUSs (ret, e2);
6163               exprNode_checkUse (ret, e2->sref, e2->loc);
6164             }
6165         }
6166
6167       if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6168         {
6169           exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6170         }
6171
6172       isjustalloc = sRef_isJustAllocated (e1->sref);
6173       isalloc = sRef_isAllocated (e1->sref);
6174
6175       if (sRef_isField (e1->sref))
6176         {
6177           sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6178           
6179           if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6180             {
6181               exprNode_checkUse (ret, root, e1->loc);
6182             }
6183           
6184         }
6185   
6186       /*
6187       ** be careful!  this defines e1->sref.
6188       */
6189
6190       /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6191
6192       DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6193       exprNode_checkSet (ret, e1->sref);
6194       
6195       if (isjustalloc) 
6196         {
6197           sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6198                                      ? e2->loc : e1->loc);
6199         }
6200       else 
6201         {
6202           if (isalloc)
6203             {
6204               sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6205             }
6206         }
6207     }
6208   
6209   return ret;
6210 }
6211
6212 exprNode
6213 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause, 
6214                /*@keep@*/ exprNode elseclause)
6215 {
6216   exprNode ret;
6217
6218   if (!exprNode_isError (pred))
6219     {
6220       ret = exprNode_createPartialCopy (pred);
6221       checkMacroParen (pred);
6222       exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6223       
6224       if (!exprNode_isError (ifclause))
6225         {
6226           checkMacroParen (ifclause);   /* update macro counts! */
6227
6228           if (!exprNode_isError (elseclause))
6229             {
6230               checkMacroParen (elseclause);
6231               
6232               if (!exprNode_matchTypes (ifclause, elseclause))
6233                 {
6234                   if (gentypeerror 
6235                       (exprNode_getType (ifclause),
6236                        ifclause,
6237                        exprNode_getType (elseclause),
6238                        elseclause,
6239                        message ("Conditional clauses are not of same type: "
6240                                 "%s (%t), %s (%t)", 
6241                                 exprNode_unparse (ifclause), 
6242                                 exprNode_getType (ifclause),
6243                                 exprNode_unparse (elseclause), 
6244                                 exprNode_getType (elseclause)),
6245                        ifclause->loc))
6246                     {
6247                       ret->sref = sRef_undefined;
6248                       ret->typ = ctype_unknown;
6249                     }
6250                 }
6251               else
6252                 {
6253                   /* for now...should merge the states */
6254                   ret->sref = ifclause->sref;
6255                   ret->typ = ifclause->typ;
6256
6257                   if (exprNode_isNullValue (ifclause))
6258                     {
6259                       ret->typ = elseclause->typ;
6260                     }
6261                 }
6262               
6263               exprNode_checkUse (ret, pred->sref, pred->loc);
6264               exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6265               exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6266
6267               exprNode_mergeCondUSs (ret, ifclause, elseclause);
6268
6269             }
6270           else
6271             {
6272               ret->typ = ifclause->typ;
6273               
6274               exprNode_checkUse (pred, pred->sref, pred->loc);
6275               exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6276               
6277               exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6278             }
6279         }
6280       else 
6281         {
6282           if (!exprNode_isError (elseclause))
6283             {
6284               ret->typ = elseclause->typ;
6285               
6286               exprNode_checkUse (pred, pred->sref, pred->loc);
6287               exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6288               
6289               exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6290             }
6291         }
6292     }
6293   else /* pred is error */
6294     {
6295       if (!exprNode_isError (ifclause))
6296         {
6297           ret = exprNode_createSemiCopy (ifclause);
6298
6299           checkMacroParen (ifclause);   /* update macro counts! */
6300           
6301           if (!exprNode_isError (elseclause))
6302             {
6303               checkMacroParen (elseclause);
6304               
6305               ret->typ = ifclause->typ;
6306                       
6307               if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6308                 {
6309                   if (gentypeerror 
6310                       (exprNode_getType (ifclause),
6311                        ifclause,
6312                        exprNode_getType (elseclause),
6313                        elseclause,
6314                        message ("Conditional clauses are not of same type: "
6315                                 "%s (%t), %s (%t)", 
6316                                 exprNode_unparse (ifclause), 
6317                                 exprNode_getType (ifclause),
6318                                 exprNode_unparse (elseclause), 
6319                                 exprNode_getType (elseclause)),
6320                        ifclause->loc))
6321                     {
6322                       ret->typ = ctype_unknown;
6323                     }
6324                 }
6325                       
6326               exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6327               exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6328               
6329               exprNode_mergeCondUSs (ret, ifclause, elseclause);
6330             }
6331         }
6332       else if (!exprNode_isError (elseclause)) /* pred, if errors */
6333         {
6334           ret = exprNode_createSemiCopy (ifclause);
6335
6336           ret->typ = elseclause->typ;
6337           checkMacroParen (elseclause);
6338           
6339           exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6340           exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6341         }
6342       else /* all errors! */
6343         {
6344           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6345         }
6346     }
6347   
6348   ret->kind = XPR_COND;
6349   ret->edata = exprData_makeCond (pred, ifclause, elseclause);  
6350
6351   if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6352     {
6353       exprNode_combineControl (ret, ifclause, elseclause);
6354     }
6355
6356   return (ret);
6357 }
6358
6359 exprNode
6360 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6361 {
6362   ctype totype = qtype_getType (qt);
6363   exprNode ret =
6364     exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6365   ctype targ;
6366
6367   /*
6368   ** check use of va_arg : <valist>, type -> type
6369   */
6370
6371   if (exprNode_isError (arg))
6372     {
6373     }
6374   else
6375     {
6376       targ = exprNode_getType (arg);
6377
6378       /*
6379       ** arg should have be a pointer
6380       */
6381
6382       if (!ctype_isUA (targ) ||
6383           (!usymId_equal (ctype_typeId (targ), 
6384                          usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6385         {
6386           voptgenerror
6387             (FLG_TYPE,
6388              message ("First argument to va_arg is not a va_list (type %t): %s",
6389                       targ, exprNode_unparse (arg)),
6390              arg->loc);
6391         }
6392
6393       exprNode_checkSet (ret, arg->sref);
6394     }
6395   
6396   /*
6397   ** return type is totype
6398   */
6399
6400   ret->typ = totype;
6401   ret->kind = XPR_VAARG;
6402   ret->edata = exprData_makeCast (tok, arg, qt);
6403
6404   return (ret);
6405 }
6406
6407 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6408 {
6409   exprNode ret = exprNode_createPlain (ctype_undefined);
6410   ret->kind = XPR_LABEL;
6411   ret->edata = exprData_makeLiteral (label);
6412   ret->isJumpPoint = TRUE;
6413
6414   return (ret); /* for now, ignore label */
6415 }
6416
6417 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6418 {
6419   if (exprNode_isDefined (stmt))
6420     {
6421       stmt->isJumpPoint = TRUE;
6422
6423       /* This prevent stray no return path errors, etc. */
6424       stmt->exitCode = XK_MUSTEXIT;
6425     }
6426
6427   return (stmt); 
6428 }
6429
6430 bool exprNode_isDefaultMarker (exprNode e) 
6431 {
6432   if (exprNode_isDefined (e))
6433     {
6434       return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6435     }
6436
6437   return FALSE;
6438 }
6439
6440 bool exprNode_isCaseMarker (exprNode e) 
6441 {
6442   if (exprNode_isDefined (e))
6443     {
6444       return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6445     }
6446
6447   return FALSE;
6448 }
6449
6450 bool exprNode_isLabelMarker (exprNode e) 
6451 {
6452   if (exprNode_isDefined (e))
6453     {
6454       return (e->kind == XPR_LABEL);
6455     }
6456
6457   return FALSE;
6458 }
6459
6460 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough) 
6461 {
6462   exprNode ret = exprNode_createPartialCopy (test);
6463
6464   ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6465
6466   if (exprNode_isError (test)) {
6467     return ret;
6468   }
6469
6470   exprNode_checkUse (ret, test->sref, test->loc);
6471   
6472   usymtab_setExitCode (ret->exitCode);
6473   
6474   if (ret->mustBreak)
6475     {
6476       usymtab_setMustBreak ();
6477     }
6478
6479   ret->edata = exprData_makeSingle (test);
6480   ret->isJumpPoint = TRUE;
6481   
6482   return ret;
6483 }
6484
6485 # if 0
6486 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6487 {
6488   exprNode ret = exprNode_createPartialCopy (test);
6489
6490   ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6491   ret->edata = exprData_makePair (test, stmt);
6492   ret->isJumpPoint = TRUE;
6493
6494   if (exprNode_isError (test))
6495     {
6496       return ret;
6497     }
6498
6499   exprNode_checkUse (ret, test->sref, test->loc);
6500   
6501   if (exprNode_isError (stmt))
6502     {
6503       return ret;
6504     }
6505   
6506   exprNode_mergeUSs (ret, stmt);
6507   
6508   ret->exitCode = stmt->exitCode;
6509   ret->mustBreak = stmt->mustBreak;
6510   ret->canBreak = stmt->canBreak;
6511
6512   usymtab_setExitCode (ret->exitCode);
6513   
6514   if (ret->mustBreak)
6515     {
6516       usymtab_setMustBreak ();
6517     }
6518   
6519   return ret;
6520 }
6521 # endif
6522
6523 /*@notnull@*/ /*@only@*/ exprNode 
6524 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6525 {
6526   exprNode ret = exprNode_createTok (def);
6527   
6528   ret->isJumpPoint = TRUE;
6529   ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6530   return (ret);
6531 }
6532
6533 bool
6534 exprNode_mayEscape (exprNode e)
6535 {
6536   if (exprNode_isDefined (e))
6537     {
6538       return exitkind_couldEscape (e->exitCode);
6539     }
6540   return FALSE;
6541 }
6542
6543 static bool
6544 exprNode_mustBreak (exprNode e)
6545 {
6546   if (exprNode_isDefined (e))
6547     {
6548       return e->mustBreak;
6549     }
6550
6551   return FALSE;
6552 }
6553
6554 bool
6555 exprNode_mustEscape (exprNode e)
6556 {
6557   if (exprNode_isDefined (e))
6558     {
6559       return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6560     }
6561
6562   return FALSE;
6563 }
6564
6565 bool
6566 exprNode_errorEscape (exprNode e)
6567 {
6568   if (exprNode_isDefined (e))
6569     {
6570       return exitkind_isError (e->exitCode);
6571     }
6572
6573   return FALSE;
6574 }
6575
6576 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6577 {
6578   exprNode ret = exprNode_createPartialCopy (e1);
6579
6580   DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6581
6582   ret->edata = exprData_makePair (e1, e2);
6583   ret->kind = XPR_STMTLIST;
6584
6585   if (exprNode_isDefined (e1))
6586     {
6587       ret->isJumpPoint = e1->isJumpPoint;
6588       ret->canBreak = e1->canBreak;
6589     }
6590   else
6591     {
6592       if (exprNode_isDefined (e2))
6593         {
6594           ret->loc = fileloc_update (ret->loc, e2->loc);
6595         }
6596     }
6597
6598   if (exprNode_isDefined (e2))
6599     {
6600       ret->exitCode = e2->exitCode;
6601       ret->mustBreak = e2->mustBreak;
6602       if (e2->canBreak) ret->canBreak = TRUE;
6603     }
6604
6605   /* 
6606   ** if e1 must return, then e2 is unreachable!
6607   */
6608
6609   if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6610     {
6611       if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1)) 
6612           && !(e2->isJumpPoint))
6613         {
6614           if (context_getFlag (FLG_UNREACHABLE))
6615             {
6616               exprNode nr = e2;
6617
6618               if (e2->kind == XPR_STMT)
6619                 {
6620                   nr = exprData_getUopNode (e2->edata);
6621                 }
6622
6623               if ((nr->kind == XPR_TOK 
6624                    && lltok_isSemi (exprData_getTok (nr->edata))))
6625                 {
6626                   /* okay to have unreachable ";" */
6627                   ret->exitCode = XK_MUSTEXIT;
6628                   ret->canBreak = TRUE;
6629                 }
6630               else
6631                 {
6632                   if (optgenerror (FLG_UNREACHABLE,
6633                                    message ("Unreachable code: %s", 
6634                                             exprNode_unparseFirst (nr)),
6635                                    exprNode_loc (nr)))
6636                     {
6637                       ret->isJumpPoint = TRUE;                
6638                       ret->mustBreak = FALSE;
6639                       ret->exitCode = XK_ERROR;
6640                       DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6641                     }
6642                   else
6643                     {
6644                       ret->exitCode = XK_MUSTEXIT;
6645                       ret->canBreak = TRUE;
6646                     }
6647
6648                 }
6649             }
6650         }
6651       else
6652         {
6653           if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6654             {
6655               /*
6656               ** We want a warning anytime we have:
6657               **         case xxx: ...  
6658               **                   yyy;  <<<- no break or return
6659               **         case zzz: ...
6660               */
6661               
6662               exprNode lastStmt = exprNode_lastStatement (e1);
6663               
6664               if (exprNode_isDefined (lastStmt) 
6665                   && !exprNode_mustEscape (lastStmt)
6666                   && !exprNode_mustBreak (lastStmt)
6667                   && !exprNode_isCaseMarker (lastStmt)
6668                   && !exprNode_isDefaultMarker (lastStmt)
6669                   && !exprNode_isLabelMarker (lastStmt))
6670                 {
6671                   voptgenerror (FLG_CASEBREAK,
6672                                 cstring_makeLiteral 
6673                                 ("Fall through case (no preceding break)"),
6674                                 e2->loc);
6675                 }
6676             }
6677         }
6678     }
6679
6680   exprNode_mergeUSs (ret, e2);
6681   
6682   usymtab_setExitCode (ret->exitCode);
6683   
6684   if (ret->mustBreak)
6685     {
6686       usymtab_setMustBreak ();
6687     }
6688
6689   return ret;
6690 }
6691
6692 exprNode exprNode_createTok (/*@only@*/ lltok t)
6693 {
6694   exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6695   ret = exprNode_create (ctype_unknown);
6696   ret->kind = XPR_TOK;
6697   ret->edata = exprData_makeTok (t);
6698   return ret;
6699 }
6700
6701 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6702 {
6703   if (!exprNode_isError (e))
6704     {
6705       exprNode_checkStatement(e);
6706     }
6707
6708   return (exprNode_statementError (e, t));
6709 }
6710
6711 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6712 {
6713   exprNode ret = exprNode_createPartialCopy (e);
6714
6715   if (!exprNode_isError (e))
6716     {
6717       if (e->kind != XPR_ASSIGN)
6718         {
6719           exprNode_checkUse (ret, e->sref, e->loc);
6720         }
6721
6722       ret->exitCode = e->exitCode;
6723       ret->canBreak = e->canBreak;
6724       ret->mustBreak = e->mustBreak;
6725     }
6726   
6727   ret->edata = exprData_makeUop (e, t);
6728   ret->kind = XPR_STMT;
6729
6730   return ret;
6731 }
6732
6733 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6734 {
6735   if (!exprNode_isError (e))
6736     {
6737       if (e->kind != XPR_ASSIGN)
6738         {
6739           exprNode_checkUse (e, e->sref, e->loc);
6740         }
6741     }
6742
6743   return e;
6744 }
6745
6746 void exprNode_produceGuards (exprNode pred)
6747 {
6748   if (!exprNode_isError (pred))
6749     {
6750       if (ctype_isRealPointer (pred->typ))
6751         {
6752           pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6753         }
6754       
6755       exprNode_checkUse (pred, pred->sref, pred->loc);
6756       exprNode_resetSref (pred);
6757     }
6758 }
6759
6760 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6761 {
6762   exprNode ret = exprNode_createPartialCopy (e);
6763
6764   if (!exprNode_isError (e))
6765     {
6766       ret->exitCode = e->exitCode;
6767       ret->canBreak = e->canBreak;
6768       ret->mustBreak = e->mustBreak;
6769     }
6770   
6771   ret->edata = exprData_makeSingle (e);
6772   ret->kind = XPR_BLOCK;
6773   return ret;
6774 }
6775
6776 bool exprNode_isBlock (exprNode e)
6777 {
6778   return (exprNode_isDefined (e) 
6779           && ((e)->kind == XPR_BLOCK));
6780 }
6781  
6782 bool exprNode_isAssign (exprNode e)
6783 {
6784   if (exprNode_isDefined (e))
6785     {
6786       return (e->kind == XPR_ASSIGN);
6787     }
6788
6789   return FALSE;
6790 }
6791
6792 bool exprNode_isEmptyStatement (exprNode e)
6793 {
6794   return (exprNode_isDefined (e) 
6795           && (e->kind == XPR_TOK)
6796           && (lltok_isSemi (exprData_getTok (e->edata))));
6797 }
6798
6799 void exprNode_checkIfPred (exprNode pred)
6800 {
6801   exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6802 }
6803
6804 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6805 {
6806   exprNode ret;
6807   bool emptyErr = FALSE;
6808
6809   if (context_maybeSet (FLG_IFEMPTY))
6810     {
6811       if (exprNode_isEmptyStatement (tclause))
6812         {
6813           emptyErr = optgenerror (FLG_IFEMPTY,
6814                                   cstring_makeLiteral
6815                                   ("Body of if statement is empty"),
6816                                   exprNode_loc (tclause));
6817         }
6818     }
6819
6820   if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6821     {
6822       if (exprNode_isDefined (tclause)
6823           && !exprNode_isBlock (tclause))
6824         {
6825           voptgenerror (FLG_IFBLOCK,
6826                         message
6827                         ("Body of if statement is not a block: %s",
6828                          exprNode_unparse (tclause)),
6829                         exprNode_loc (tclause));
6830         }
6831     }
6832
6833   if (exprNode_isError (pred))
6834     {
6835       if (exprNode_isError (tclause))
6836         {
6837           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6838         }
6839       else
6840         {
6841           ret = exprNode_createPartialCopy (tclause);
6842         }
6843     }
6844   else
6845     {
6846       if (exprNode_mustEscape (pred))
6847         {
6848           voptgenerror 
6849             (FLG_UNREACHABLE,
6850              message ("Predicate always exits: %s", exprNode_unparse (pred)),
6851              exprNode_loc (pred));
6852         }
6853       
6854       /*! exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); */ /*@i523@*/
6855       exprNode_checkUse (pred, pred->sref, pred->loc);
6856       
6857       if (!exprNode_isError (tclause))
6858         {
6859           exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6860         }
6861       
6862       ret = exprNode_createPartialCopy (pred);
6863     }
6864
6865   ret->kind = XPR_IF;
6866   ret->edata = exprData_makePair (pred, tclause);
6867
6868   ret->exitCode = XK_UNKNOWN;
6869
6870   if (exprNode_isDefined (tclause))
6871     {
6872       ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6873       ret->canBreak = tclause->canBreak;
6874       ret->sets = sRefSet_union (ret->sets, tclause->sets);
6875       ret->msets = sRefSet_union (ret->msets, tclause->msets);
6876       ret->uses = sRefSet_union (ret->uses, tclause->uses);
6877     }
6878
6879   ret->mustBreak = FALSE;
6880
6881   return ret;
6882 }
6883
6884 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6885                           /*@only@*/ exprNode tclause, 
6886                           /*@only@*/ exprNode eclause)
6887 {
6888   exprNode ret;
6889   bool tEmptyErr = FALSE;
6890   bool eEmptyErr = FALSE;
6891
6892   if (context_maybeSet (FLG_IFEMPTY))
6893     {
6894       if (exprNode_isEmptyStatement (tclause))
6895         {
6896           tEmptyErr = optgenerror 
6897             (FLG_IFEMPTY,
6898              cstring_makeLiteral
6899              ("Body of if clause of if statement is empty"),
6900              exprNode_loc (tclause));
6901         }
6902
6903       if (exprNode_isEmptyStatement (eclause))
6904         {
6905           eEmptyErr = optgenerror 
6906             (FLG_IFEMPTY,
6907              cstring_makeLiteral
6908              ("Body of else clause of if statement is empty"),
6909              exprNode_loc (eclause));
6910         }
6911     }
6912
6913   if (context_maybeSet (FLG_IFBLOCK))
6914     {
6915       if (!tEmptyErr
6916           && exprNode_isDefined (tclause)
6917           && !exprNode_isBlock (tclause))
6918         {
6919           voptgenerror (FLG_IFBLOCK,
6920                         message
6921                         ("Body of if clause of if statement is not a block: %s",
6922                          exprNode_unparse (tclause)),
6923                         exprNode_loc (tclause));
6924         }
6925
6926       if (!eEmptyErr
6927           && exprNode_isDefined (eclause)
6928           && !exprNode_isBlock (eclause)
6929           && !(eclause->kind == XPR_IF)
6930           && !(eclause->kind == XPR_IFELSE))
6931         {
6932           voptgenerror
6933             (FLG_IFBLOCK,
6934              message
6935              ("Body of else clause of if statement is not a block: %s",
6936               exprNode_unparse (eclause)),
6937              exprNode_loc (eclause));
6938         }
6939     }
6940
6941   if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6942     {
6943       if (exprNode_isDefined (eclause)
6944           && (eclause->kind == XPR_IF))
6945         {
6946           voptgenerror (FLG_ELSEIFCOMPLETE,
6947                         message ("Incomplete else if logic (no final else): %s",
6948                                  exprNode_unparse (eclause)),
6949                         exprNode_loc (eclause));
6950         }
6951     }
6952
6953   if (exprNode_isError (pred))
6954     {
6955       if (exprNode_isError (tclause))
6956         {
6957           if (exprNode_isError (eclause))
6958             {
6959               ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6960             }
6961           else
6962             {
6963               ret = exprNode_createPartialCopy (eclause);
6964             }
6965         }
6966       else 
6967         {
6968           ret = exprNode_createPartialCopy (tclause);
6969         }
6970     }
6971   else /* pred is okay */
6972     {
6973       ret = exprNode_createPartialCopy (pred);
6974
6975       if (exprNode_mustEscape (pred))
6976         {
6977           voptgenerror
6978             (FLG_UNREACHABLE,
6979              message ("Predicate always exits: %s", exprNode_unparse (pred)),
6980              exprNode_loc (pred));
6981         }
6982       
6983       /*@i3423 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);*/
6984       exprNode_checkUse (ret, pred->sref, pred->loc);
6985       
6986       exprNode_mergeCondUSs (ret, tclause, eclause);
6987     }
6988
6989   ret->kind = XPR_IFELSE;
6990   ret->edata = exprData_makeCond (pred, tclause, eclause);
6991
6992   if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6993     {
6994       exprNode_combineControl (ret, tclause, eclause);
6995       ret->loc = fileloc_update (ret->loc, eclause->loc);
6996     }
6997
6998   return ret;
6999 }
7000
7001 /*
7002 ** *allpaths <- TRUE iff all executions paths must go through the switch
7003 */
7004
7005 static bool
7006 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7007 {
7008   exprNodeSList el = exprNode_flatten (e);
7009   bool mustReturn = TRUE; /* find a branch that doesn't */
7010   bool thisReturn = FALSE;
7011   bool hasDefault = FALSE;
7012   bool hasAllMembers = FALSE;
7013   bool inSwitch = FALSE;
7014   bool isEnumSwitch = FALSE;
7015   bool canBreak = FALSE;
7016   bool fallThrough = FALSE;
7017   ctype ct = ctype_unknown;
7018   enumNameSList usedEnums;
7019   enumNameList enums;
7020
7021   if (exprNode_isDefined (test))
7022     {
7023       ctype ttype;
7024
7025       ct = test->typ;
7026       ttype = ctype_realType (ct);
7027
7028       if (ctype_isEnum (ttype))
7029         {
7030           isEnumSwitch = TRUE;
7031           enums = ctype_elist (ttype);
7032           usedEnums = enumNameSList_new ();
7033         }
7034     }
7035
7036   exprNodeSList_elements (el, current)
7037     {
7038       
7039       DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(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.979595 seconds and 3 git commands to generate.