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