]> andersk Git - splint.git/blob - src/exprNode.c
Added support for omitted if clauses in conditionals, patch provided by peteran.
[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_condIfOmit (/*@keep@*/ exprNode pred, 
6477                      /*@keep@*/ exprNode elseclause)
6478 {
6479   exprNode ifclause = exprNode_createPartialCopy (pred);
6480
6481   if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (pred)))
6482     {
6483       (void) llgenhinterror 
6484         (FLG_SYNTAX,
6485          message ("Conditionals with Omitted Operands is not supported by ISO C99"),
6486          message ("Use +gnuextensions to allow compound statement "
6487                   "expressions (and other GNU language extensions) "
6488                   "without this warning"),
6489          exprNode_loc (pred));
6490     }
6491   
6492   return exprNode_cond(pred, ifclause, elseclause);
6493 }
6494
6495 exprNode
6496 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6497 {
6498   ctype totype = qtype_getType (qt);
6499   exprNode ret =
6500     exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6501   ctype targ;
6502
6503   /*
6504   ** check use of va_arg : <valist>, type -> type
6505   */
6506
6507   if (exprNode_isError (arg))
6508     {
6509     }
6510   else
6511     {
6512       targ = exprNode_getType (arg);
6513
6514       /*
6515       ** arg should have be a pointer
6516       */
6517
6518       if (!ctype_isUA (targ) ||
6519           (!typeId_equal (ctype_typeId (targ), 
6520                           usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6521         {
6522           voptgenerror
6523             (FLG_TYPE,
6524              message ("First argument to va_arg is not a va_list (type %t): %s",
6525                       targ, exprNode_unparse (arg)),
6526              arg->loc);
6527         }
6528
6529       exprNode_checkSet (ret, arg->sref);
6530     }
6531   
6532   /*
6533   ** return type is totype
6534   */
6535
6536   ret->typ = totype;
6537   ret->kind = XPR_VAARG;
6538   ret->edata = exprData_makeCast (tok, arg, qt);
6539
6540   return (ret);
6541 }
6542
6543 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6544 {
6545   exprNode ret = exprNode_createPlain (ctype_undefined);
6546   ret->kind = XPR_LABEL;
6547   ret->edata = exprData_makeLiteral (label);
6548   ret->isJumpPoint = TRUE;
6549
6550   return (ret); /* for now, ignore label */
6551 }
6552
6553 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6554 {
6555   if (exprNode_isDefined (stmt))
6556     {
6557       stmt->isJumpPoint = TRUE;
6558
6559       /* This prevent stray no return path errors, etc. */
6560       stmt->exitCode = XK_MUSTEXIT;
6561     }
6562
6563   return (stmt); 
6564 }
6565
6566 bool exprNode_isDefaultMarker (exprNode e) 
6567 {
6568   if (exprNode_isDefined (e))
6569     {
6570       return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6571     }
6572
6573   return FALSE;
6574 }
6575
6576 bool exprNode_isCaseMarker (exprNode e) 
6577 {
6578   if (exprNode_isDefined (e))
6579     {
6580       return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6581     }
6582
6583   return FALSE;
6584 }
6585
6586 bool exprNode_isLabelMarker (exprNode e) 
6587 {
6588   if (exprNode_isDefined (e))
6589     {
6590       return (e->kind == XPR_LABEL);
6591     }
6592
6593   return FALSE;
6594 }
6595
6596 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough) 
6597 {
6598   exprNode ret = exprNode_createPartialCopy (test);
6599
6600   ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6601
6602   if (exprNode_isError (test)) {
6603     return ret;
6604   }
6605
6606   exprNode_checkUse (ret, test->sref, test->loc);
6607   
6608   usymtab_setExitCode (ret->exitCode);
6609   
6610   if (ret->mustBreak)
6611     {
6612       usymtab_setMustBreak ();
6613     }
6614
6615   ret->edata = exprData_makeSingle (test);
6616   ret->isJumpPoint = TRUE;
6617   
6618   return ret;
6619 }
6620
6621 # if 0
6622 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6623 {
6624   exprNode ret = exprNode_createPartialCopy (test);
6625
6626   ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6627   ret->edata = exprData_makePair (test, stmt);
6628   ret->isJumpPoint = TRUE;
6629
6630   if (exprNode_isError (test))
6631     {
6632       return ret;
6633     }
6634
6635   exprNode_checkUse (ret, test->sref, test->loc);
6636   
6637   if (exprNode_isError (stmt))
6638     {
6639       return ret;
6640     }
6641   
6642   exprNode_mergeUSs (ret, stmt);
6643   
6644   ret->exitCode = stmt->exitCode;
6645   ret->mustBreak = stmt->mustBreak;
6646   ret->canBreak = stmt->canBreak;
6647
6648   usymtab_setExitCode (ret->exitCode);
6649   
6650   if (ret->mustBreak)
6651     {
6652       usymtab_setMustBreak ();
6653     }
6654   
6655   return ret;
6656 }
6657 # endif
6658
6659 /*@notnull@*/ /*@only@*/ exprNode 
6660 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6661 {
6662   exprNode ret = exprNode_createTok (def);
6663   
6664   ret->isJumpPoint = TRUE;
6665   ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6666   return (ret);
6667 }
6668
6669 bool
6670 exprNode_mayEscape (exprNode e)
6671 {
6672   if (exprNode_isDefined (e))
6673     {
6674       return exitkind_couldEscape (e->exitCode);
6675     }
6676   return FALSE;
6677 }
6678
6679 static bool
6680 exprNode_mustBreak (exprNode e)
6681 {
6682   if (exprNode_isDefined (e))
6683     {
6684       return e->mustBreak;
6685     }
6686
6687   return FALSE;
6688 }
6689
6690 bool
6691 exprNode_mustEscape (exprNode e)
6692 {
6693   if (exprNode_isDefined (e))
6694     {
6695       return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6696     }
6697
6698   return FALSE;
6699 }
6700
6701 bool
6702 exprNode_errorEscape (exprNode e)
6703 {
6704   if (exprNode_isDefined (e))
6705     {
6706       return exitkind_isError (e->exitCode);
6707     }
6708
6709   return FALSE;
6710 }
6711
6712 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6713 {
6714   exprNode ret = exprNode_createPartialCopy (e1);
6715
6716   DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6717
6718   ret->edata = exprData_makePair (e1, e2);
6719   ret->kind = XPR_STMTLIST;
6720
6721   if (exprNode_isDefined (e1))
6722     {
6723       ret->isJumpPoint = e1->isJumpPoint;
6724       ret->canBreak = e1->canBreak;
6725     }
6726   else
6727     {
6728       if (exprNode_isDefined (e2))
6729         {
6730           ret->loc = fileloc_update (ret->loc, e2->loc);
6731         }
6732     }
6733
6734   if (exprNode_isDefined (e2))
6735     {
6736       ret->exitCode = e2->exitCode;
6737       ret->mustBreak = e2->mustBreak;
6738       if (e2->canBreak) ret->canBreak = TRUE;
6739     }
6740
6741   /* 
6742   ** if e1 must return, then e2 is unreachable!
6743   */
6744
6745   if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6746     {
6747       if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1)) 
6748           && !(e2->isJumpPoint))
6749         {
6750           if (context_getFlag (FLG_UNREACHABLE))
6751             {
6752               exprNode nr = e2;
6753
6754               if (e2->kind == XPR_STMT)
6755                 {
6756                   nr = exprData_getUopNode (e2->edata);
6757                 }
6758
6759               if ((nr->kind == XPR_TOK 
6760                    && lltok_isSemi (exprData_getTok (nr->edata))))
6761                 {
6762                   /* okay to have unreachable ";" */
6763                   ret->exitCode = XK_MUSTEXIT;
6764                   ret->canBreak = TRUE;
6765                 }
6766               else
6767                 {
6768                   if (optgenerror (FLG_UNREACHABLE,
6769                                    message ("Unreachable code: %s", 
6770                                             exprNode_unparseFirst (nr)),
6771                                    exprNode_loc (nr)))
6772                     {
6773                       ret->isJumpPoint = TRUE;                
6774                       ret->mustBreak = FALSE;
6775                       ret->exitCode = XK_ERROR;
6776                       DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6777                     }
6778                   else
6779                     {
6780                       ret->exitCode = XK_MUSTEXIT;
6781                       ret->canBreak = TRUE;
6782                     }
6783
6784                 }
6785             }
6786         }
6787       else
6788         {
6789           if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6790             {
6791               /*
6792               ** We want a warning anytime we have:
6793               **         case xxx: ...  
6794               **                   yyy;  <<<- no break or return
6795               **         case zzz: ...
6796               */
6797               
6798               exprNode lastStmt = exprNode_lastStatement (e1);
6799               
6800               if (exprNode_isDefined (lastStmt) 
6801                   && !exprNode_mustEscape (lastStmt)
6802                   && !exprNode_mustBreak (lastStmt)
6803                   && !exprNode_isCaseMarker (lastStmt)
6804                   && !exprNode_isDefaultMarker (lastStmt)
6805                   && !exprNode_isLabelMarker (lastStmt))
6806                 {
6807                   voptgenerror (FLG_CASEBREAK,
6808                                 cstring_makeLiteral 
6809                                 ("Fall through case (no preceding break)"),
6810                                 e2->loc);
6811                 }
6812             }
6813         }
6814     }
6815
6816   exprNode_mergeUSs (ret, e2);
6817   
6818   usymtab_setExitCode (ret->exitCode);
6819   
6820   if (ret->mustBreak)
6821     {
6822       usymtab_setMustBreak ();
6823     }
6824
6825   DPRINTF (("==> %s", exprNode_unparse (ret)));
6826   return ret;
6827 }
6828
6829 exprNode exprNode_createTok (/*@only@*/ lltok t)
6830 {
6831   exprNode ret = exprNode_create (ctype_unknown);
6832   ret->kind = XPR_TOK;
6833   ret->edata = exprData_makeTok (t);
6834   return ret;
6835 }
6836
6837 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6838 {
6839   if (!exprNode_isError (e))
6840     {
6841       exprChecks_checkStatementEffect(e);
6842     }
6843
6844   return (exprNode_statementError (e, t));
6845 }
6846
6847 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6848 {
6849   exprNode ret = exprNode_createPartialCopy (e);
6850
6851   if (!exprNode_isError (e))
6852     {
6853       if (e->kind != XPR_ASSIGN)
6854         {
6855           exprNode_checkUse (ret, e->sref, e->loc);
6856         }
6857
6858       ret->exitCode = e->exitCode;
6859       ret->canBreak = e->canBreak;
6860       ret->mustBreak = e->mustBreak;
6861     }
6862   
6863   ret->edata = exprData_makeUop (e, t);
6864   ret->kind = XPR_STMT;
6865
6866   return ret;
6867 }
6868
6869 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6870 {
6871   if (!exprNode_isError (e))
6872     {
6873       if (e->kind != XPR_ASSIGN)
6874         {
6875           exprNode_checkUse (e, e->sref, e->loc);
6876         }
6877     }
6878
6879   return e;
6880 }
6881
6882 void exprNode_produceGuards (exprNode pred)
6883 {
6884   if (!exprNode_isError (pred))
6885     {
6886       if (ctype_isRealPointer (pred->typ))
6887         {
6888           pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6889         }
6890       
6891       exprNode_checkUse (pred, pred->sref, pred->loc);
6892       exprNode_resetSref (pred);
6893     }
6894 }
6895
6896 exprNode exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen, /*@only@*/ exprNode e)
6897 {
6898   exprNode laststmt;
6899
6900   DPRINTF (("Compound: %s", exprNode_unparse (e)));
6901
6902   if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (e)))
6903     {
6904       (void) llgenhinterror 
6905         (FLG_SYNTAX,
6906          message ("Compound statement expressions is not supported by ISO C99"),
6907          message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) "
6908                   "without this warning"),
6909          exprNode_loc (e));
6910     }
6911
6912   /*
6913   ** The type of a compoundStatementExpression is the type of the last statement 
6914   */
6915   
6916   llassert (exprNode_isBlock (e));
6917   laststmt = exprNode_lastStatement (e);
6918
6919   DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt), ctype_unparse (exprNode_getType (laststmt))));
6920   DPRINTF (("e: %s", exprNode_unparse (e)));
6921   e->typ = exprNode_getType (laststmt);
6922   return exprNode_addParens (tlparen, e);
6923 }
6924
6925
6926 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6927 {
6928   exprNode ret = exprNode_createPartialCopy (e);
6929
6930   if (!exprNode_isError (e))
6931     {
6932       ret->exitCode = e->exitCode;
6933       ret->canBreak = e->canBreak;
6934       ret->mustBreak = e->mustBreak;
6935     }
6936   
6937   DPRINTF (("Block e: %s", exprNode_unparse (e)));
6938   ret->edata = exprData_makeSingle (e);
6939   ret->kind = XPR_BLOCK;
6940   DPRINTF (("Block: %s", exprNode_unparse (ret)));
6941   return ret;
6942 }
6943
6944 bool exprNode_isBlock (exprNode e)
6945 {
6946   return (exprNode_isDefined (e) 
6947           && ((e)->kind == XPR_BLOCK));
6948 }
6949
6950 bool exprNode_isStatement (exprNode e)
6951 {
6952   return (exprNode_isDefined (e) 
6953           && ((e)->kind == XPR_STMT));
6954 }
6955  
6956 bool exprNode_isAssign (exprNode e)
6957 {
6958   if (exprNode_isDefined (e))
6959     {
6960       return (e->kind == XPR_ASSIGN);
6961     }
6962
6963   return FALSE;
6964 }
6965
6966 bool exprNode_isEmptyStatement (exprNode e)
6967 {
6968   return (exprNode_isDefined (e) 
6969           && (e->kind == XPR_TOK)
6970           && (lltok_isSemi (exprData_getTok (e->edata))));
6971 }
6972
6973 bool exprNode_isMultiStatement (exprNode e)
6974 {
6975   return (exprNode_isDefined (e)
6976           && ((e->kind == XPR_FOR)
6977               || (e->kind == XPR_FORPRED)
6978               || (e->kind == XPR_IF)
6979               || (e->kind == XPR_IFELSE)
6980               || (e->kind == XPR_WHILE)
6981               || (e->kind == XPR_WHILEPRED)
6982               || (e->kind == XPR_DOWHILE)
6983               || (e->kind == XPR_BLOCK)
6984               || (e->kind == XPR_STMT)
6985               || (e->kind == XPR_STMTLIST)
6986               || (e->kind == XPR_SWITCH)));
6987 }
6988
6989 void exprNode_checkIfPred (exprNode pred)
6990 {
6991   exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6992 }
6993
6994 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6995 {
6996   exprNode ret;
6997   bool emptyErr = FALSE;
6998
6999   if (context_maybeSet (FLG_IFEMPTY))
7000     {
7001       if (exprNode_isEmptyStatement (tclause))
7002         {
7003           emptyErr = optgenerror (FLG_IFEMPTY,
7004                                   cstring_makeLiteral
7005                                   ("Body of if statement is empty"),
7006                                   exprNode_loc (tclause));
7007         }
7008     }
7009
7010   if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
7011     {
7012       if (exprNode_isDefined (tclause)
7013           && !exprNode_isBlock (tclause))
7014         {
7015           voptgenerror (FLG_IFBLOCK,
7016                         message
7017                         ("Body of if statement is not a block: %s",
7018                          exprNode_unparse (tclause)),
7019                         exprNode_loc (tclause));
7020         }
7021     }
7022
7023   if (exprNode_isError (pred))
7024     {
7025       if (exprNode_isError (tclause))
7026         {
7027           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7028         }
7029       else
7030         {
7031           ret = exprNode_createPartialCopy (tclause);
7032         }
7033     }
7034   else
7035     {
7036       if (exprNode_mustEscape (pred))
7037         {
7038           voptgenerror 
7039             (FLG_UNREACHABLE,
7040              message ("Predicate always exits: %s", exprNode_unparse (pred)),
7041              exprNode_loc (pred));
7042         }
7043       
7044       exprNode_checkUse (pred, pred->sref, pred->loc);
7045       
7046       if (!exprNode_isError (tclause))
7047         {
7048           exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
7049         }
7050       
7051       ret = exprNode_createPartialCopy (pred);
7052     }
7053
7054   ret->kind = XPR_IF;
7055   ret->edata = exprData_makePair (pred, tclause);
7056
7057   ret->exitCode = XK_UNKNOWN;
7058
7059   if (exprNode_isDefined (tclause))
7060     {
7061       ret->exitCode = exitkind_makeConditional (tclause->exitCode);
7062       ret->canBreak = tclause->canBreak;
7063       ret->sets = sRefSet_union (ret->sets, tclause->sets);
7064       ret->msets = sRefSet_union (ret->msets, tclause->msets);
7065       ret->uses = sRefSet_union (ret->uses, tclause->uses);
7066     }
7067
7068   ret->mustBreak = FALSE;
7069
7070   return ret;
7071 }
7072
7073 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
7074                           /*@only@*/ exprNode tclause, 
7075                           /*@only@*/ exprNode eclause)
7076 {
7077   exprNode ret;
7078   bool tEmptyErr = FALSE;
7079   bool eEmptyErr = FALSE;
7080
7081   if (context_maybeSet (FLG_IFEMPTY))
7082     {
7083       if (exprNode_isEmptyStatement (tclause))
7084         {
7085           tEmptyErr = optgenerror 
7086             (FLG_IFEMPTY,
7087              cstring_makeLiteral
7088              ("Body of if clause of if statement is empty"),
7089              exprNode_loc (tclause));
7090         }
7091
7092       if (exprNode_isEmptyStatement (eclause))
7093         {
7094           eEmptyErr = optgenerror 
7095             (FLG_IFEMPTY,
7096              cstring_makeLiteral
7097              ("Body of else clause of if statement is empty"),
7098              exprNode_loc (eclause));
7099         }
7100     }
7101
7102   if (context_maybeSet (FLG_IFBLOCK))
7103     {
7104       if (!tEmptyErr
7105           && exprNode_isDefined (tclause)
7106           && !exprNode_isBlock (tclause))
7107         {
7108           voptgenerror (FLG_IFBLOCK,
7109                         message
7110                         ("Body of if clause of if statement is not a block: %s",
7111                          exprNode_unparse (tclause)),
7112                         exprNode_loc (tclause));
7113         }
7114
7115       if (!eEmptyErr
7116           && exprNode_isDefined (eclause)
7117           && !exprNode_isBlock (eclause)
7118           && !(eclause->kind == XPR_IF)
7119           && !(eclause->kind == XPR_IFELSE))
7120         {
7121           voptgenerror
7122             (FLG_IFBLOCK,
7123              message
7124              ("Body of else clause of if statement is not a block: %s",
7125               exprNode_unparse (eclause)),
7126              exprNode_loc (eclause));
7127         }
7128     }
7129
7130   if (context_maybeSet (FLG_ELSEIFCOMPLETE))
7131     {
7132       if (exprNode_isDefined (eclause)
7133           && (eclause->kind == XPR_IF))
7134         {
7135           voptgenerror (FLG_ELSEIFCOMPLETE,
7136                         message ("Incomplete else if logic (no final else): %s",
7137                                  exprNode_unparse (eclause)),
7138                         exprNode_loc (eclause));
7139         }
7140     }
7141
7142   if (exprNode_isError (pred))
7143     {
7144       if (exprNode_isError (tclause))
7145         {
7146           if (exprNode_isError (eclause))
7147             {
7148               ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7149             }
7150           else
7151             {
7152               ret = exprNode_createPartialCopy (eclause);
7153             }
7154         }
7155       else 
7156         {
7157           ret = exprNode_createPartialCopy (tclause);
7158         }
7159     }
7160   else /* pred is okay */
7161     {
7162       ret = exprNode_createPartialCopy (pred);
7163
7164       if (exprNode_mustEscape (pred))
7165         {
7166           voptgenerror
7167             (FLG_UNREACHABLE,
7168              message ("Predicate always exits: %s", exprNode_unparse (pred)),
7169              exprNode_loc (pred));
7170         }
7171       
7172       exprNode_checkUse (ret, pred->sref, pred->loc);
7173       exprNode_mergeCondUSs (ret, tclause, eclause);
7174     }
7175
7176   ret->kind = XPR_IFELSE;
7177   ret->edata = exprData_makeCond (pred, tclause, eclause);
7178
7179   if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
7180     {
7181       exprNode_combineControl (ret, tclause, eclause);
7182       ret->loc = fileloc_update (ret->loc, eclause->loc);
7183     }
7184
7185   return ret;
7186 }
7187
7188 /*
7189 ** *allpaths <- TRUE iff all executions paths must go through the switch
7190 */
7191
7192 static bool
7193 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7194 {
7195   exprNodeSList el = exprNode_flatten (e);
7196   bool mustReturn = TRUE; /* find a branch that doesn't */
7197   bool thisReturn = FALSE;
7198   bool hasDefault = FALSE;
7199   bool hasAllMembers = FALSE;
7200   bool inSwitch = FALSE;
7201   bool isEnumSwitch = FALSE;
7202   bool canBreak = FALSE;
7203   bool fallThrough = FALSE;
7204   ctype ct = ctype_unknown;
7205   enumNameSList usedEnums;
7206   enumNameList enums;
7207
7208   if (exprNode_isDefined (test))
7209     {
7210       ctype ttype;
7211
7212       ct = test->typ;
7213       ttype = ctype_realType (ct);
7214
7215       if (ctype_isEnum (ttype))
7216         {
7217           isEnumSwitch = TRUE;
7218           enums = ctype_elist (ttype);
7219           usedEnums = enumNameSList_new ();
7220         }
7221     }
7222
7223   exprNodeSList_elements (el, current)
7224     {
7225       
7226       DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
7227       
7228       if (exprNode_isDefined (current))
7229         {
7230           switch (current->kind)
7231             {
7232             case XPR_FTDEFAULT:
7233             case XPR_DEFAULT:
7234               if (hasDefault)
7235                 {
7236                   voptgenerror 
7237                     (FLG_DUPLICATECASES,
7238                      message ("Duplicate default cases in switch"),
7239                      exprNode_loc (current));
7240                 }          
7241             /*@fallthrough@*/
7242             case XPR_FTCASE:
7243             case XPR_CASE: 
7244               if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7245                 {
7246                   hasDefault = TRUE; 
7247                 }
7248               else
7249                 {
7250                   if (isEnumSwitch)
7251                     {
7252                       exprNode st = exprData_getSingle (current->edata);
7253                       uentry ue = exprNode_getUentry (st);
7254                       
7255                       if (uentry_isValid (ue))
7256                         {
7257                           cstring cname = uentry_rawName (ue);
7258                           
7259                           if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7260                             {
7261                               if (enumNameSList_member
7262                                   (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7263                                 {
7264                                   voptgenerror
7265                                     (FLG_DUPLICATECASES,
7266                                      message ("Duplicate case in switch: %s", 
7267                                               cname),
7268                                      current->loc);
7269                                 }
7270                               else
7271                                 {
7272                                   enumNameSList_addh (usedEnums, cname);
7273                                 }
7274                             }
7275                           else
7276                             {
7277                               voptgenerror 
7278                                 (FLG_TYPE,
7279                                  message ("Case in switch not %s member: %s", 
7280                                           ctype_unparse (ct), cname),
7281                                  current->loc);
7282                             }
7283                         }
7284                     }
7285                 }
7286               
7287               if (inSwitch && !fallThrough)
7288                 {
7289                   if (!thisReturn || canBreak) 
7290                     {
7291                       mustReturn = FALSE;
7292                     }
7293                 }
7294               
7295               fallThrough = TRUE;
7296               inSwitch = TRUE;
7297               thisReturn = FALSE;
7298               canBreak = FALSE;
7299               /*@switchbreak@*/ break;
7300             default:
7301               thisReturn = thisReturn || exprNode_mustEscape (current);
7302               canBreak = canBreak || current->canBreak;
7303               if (canBreak) fallThrough = FALSE;
7304             }
7305         }
7306     } end_exprNodeSList_elements;
7307
7308   if (inSwitch) /* check the last one! */
7309     {
7310       if (!thisReturn || canBreak) 
7311         {
7312           mustReturn = FALSE;
7313         }
7314     }
7315   
7316   if (isEnumSwitch)
7317     {
7318       if (!hasDefault 
7319           && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) != 
7320               enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7321         {
7322           enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7323           
7324           voptgenerror (FLG_MISSCASE,
7325                         message ("Missing case%s in switch: %q",
7326                                  cstring_makeLiteralTemp 
7327                                  ((enumNameSList_size (unused) > 1) ? "s" : ""),
7328                                  enumNameSList_unparse (unused)),
7329                         g_currentloc);
7330
7331           enumNameSList_free (unused);
7332           *allpaths = FALSE; /* evans 2002-01-01 */
7333         }
7334       else
7335         {
7336           hasAllMembers = TRUE;
7337           *allpaths = TRUE;
7338         }
7339
7340       enumNameSList_free (usedEnums);
7341     }
7342   else
7343     {
7344       *allpaths = hasDefault;
7345     }
7346
7347   exprNodeSList_free (el);
7348   return ((hasDefault || hasAllMembers) && mustReturn);  
7349 }
7350     
7351 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7352 {
7353   exprNode ret = exprNode_createPartialCopy (e);
7354   bool allpaths;
7355
7356   DPRINTF (("Switch: %s", exprNode_unparse (s)));
7357
7358   ret->kind = XPR_SWITCH;
7359   ret->edata = exprData_makePair (e, s);
7360   
7361   if (!exprNode_isError (s))
7362     {
7363       exprNode fs = exprNode_firstStatement (s);
7364       ret->loc = fileloc_update (ret->loc, s->loc);
7365
7366       if (exprNode_isUndefined (fs) 
7367           || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7368           || exprNode_isDefaultMarker (fs)) {
7369         ;
7370       } else {
7371         voptgenerror (FLG_FIRSTCASE,
7372                       message
7373                       ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7374                       fs->loc);
7375       }
7376     }
7377
7378   if (!exprNode_isError (e)) 
7379     {
7380       if (checkSwitchExpr (e, s, &allpaths))
7381         {
7382           ret->exitCode = XK_MUSTRETURN;
7383         }
7384       else
7385         {
7386           ret->exitCode = e->exitCode;
7387         }
7388
7389       ret->canBreak = e->canBreak;
7390       ret->mustBreak = e->mustBreak;
7391     }
7392   /*
7393   ** forgot this!
7394   **   exprNode.c:3883,32: Variable allpaths used before definition
7395   */
7396   else 
7397     {
7398       allpaths = FALSE;
7399     }
7400   
7401   DPRINTF (("Context exit switch!"));
7402   context_exitSwitch (ret, allpaths);
7403   DPRINTF (("Context exit switch done!"));
7404
7405   return ret;
7406 }
7407
7408 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7409                                /*@notnull@*/ exprNode body)
7410 {
7411   sRefSet tuses = test->uses;
7412   
7413   if (!sRefSet_isEmpty (test->uses))
7414     {
7415       sRefSet sets = sRefSet_newCopy (body->sets);
7416       bool hasError = TRUE;
7417       bool innerState = FALSE;
7418       sRefSet tuncon = sRefSet_undefined;
7419       
7420       sets = sRefSet_union (sets, test->sets);
7421       sets = sRefSet_union (sets, body->msets);
7422       sets = sRefSet_union (sets, test->msets);
7423
7424       sRefSet_allElements (tuses, el)
7425         {
7426           if (sRef_isUnconstrained (el))
7427             {
7428               tuncon = sRefSet_insert (tuncon, el);
7429             }
7430           else
7431             {
7432               if (sRefSet_member (sets, el))
7433                 {
7434                   hasError = FALSE;
7435                   break;
7436                 }
7437             }
7438
7439           if (sRef_isInternalState (el)
7440               || sRef_isFileStatic (sRef_getRootBase (el)))
7441             {
7442               innerState = TRUE;
7443             }
7444         } end_sRefSet_allElements ;
7445
7446       if (hasError)
7447         {
7448           sRefSet suncon = sRefSet_undefined;
7449           bool sinner = FALSE;
7450
7451           sRefSet_allElements (sets, el)
7452             {
7453               if (sRef_isUnconstrained (el))
7454                 {
7455                   suncon = sRefSet_insert (suncon, el);
7456                 }
7457               else if (sRef_isInternalState (el))
7458                 {
7459                   sinner = TRUE;
7460                 }
7461               else
7462                 {
7463                   ;
7464                 }
7465             } end_sRefSet_allElements ;
7466
7467           if (sinner && innerState)
7468             {
7469               ; 
7470             }
7471           else if (sRefSet_isEmpty (tuncon)
7472                    && sRefSet_isEmpty (suncon))
7473             {
7474               voptgenerror 
7475                 (FLG_INFLOOPS,
7476                  message
7477                  ("Suspected infinite loop.  No value used in loop test (%q) "
7478                   "is modified by test or loop body.",
7479                   sRefSet_unparsePlain (tuses)), 
7480                  test->loc);
7481             }
7482           else
7483             {
7484               if (sRefSet_isEmpty (tuncon))
7485                 {
7486                   voptgenerror 
7487                     (FLG_INFLOOPSUNCON,
7488                      message ("Suspected infinite loop.  No condition values "
7489                               "modified.  Modification possible through "
7490                               "unconstrained calls: %q",
7491                               sRefSet_unparsePlain (suncon)), 
7492                      test->loc);
7493                 }
7494               else
7495                 {
7496                   voptgenerror 
7497                     (FLG_INFLOOPSUNCON,
7498                      message ("Suspected infinite loop.  No condition values "
7499                               "modified.  Possible undetected dependency through "
7500                               "unconstrained calls in loop test: %q",
7501                               sRefSet_unparsePlain (tuncon)), 
7502                      test->loc);
7503                 }
7504             }
7505         }
7506
7507       sRefSet_free (sets);
7508     }
7509 }
7510
7511 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7512 {
7513   exprNode ret;
7514   bool emptyErr = FALSE;
7515   
7516   if (context_maybeSet (FLG_WHILEEMPTY))
7517     {
7518       if (exprNode_isEmptyStatement (b))
7519         {
7520           emptyErr = optgenerror 
7521             (FLG_WHILEEMPTY,
7522              cstring_makeLiteral
7523              ("Body of while statement is empty"),
7524              exprNode_loc (b));
7525         }
7526     }
7527
7528   if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7529     {
7530       if (exprNode_isDefined (b)
7531           && !exprNode_isBlock (b))
7532         {
7533           if (context_inIterDef ()
7534               && (b->kind == XPR_STMTLIST
7535                   || b->kind == XPR_TOK))
7536             {
7537               ; /* no error */
7538             }
7539           else
7540             {
7541               voptgenerror (FLG_WHILEBLOCK,
7542                             message
7543                             ("Body of while statement is not a block: %s",
7544                              exprNode_unparse (b)),
7545                             exprNode_loc (b));
7546             }
7547         }
7548     }
7549   
7550   if (exprNode_isError (t))
7551     {
7552       if (exprNode_isError (b))
7553         {
7554           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7555         }
7556       else
7557         {
7558           ret = exprNode_createPartialCopy (b);
7559         }
7560     }
7561   else
7562     {
7563       exprNode test;
7564
7565       ret = exprNode_createPartialCopy (t);
7566       
7567       llassert (t->kind == XPR_WHILEPRED);
7568
7569       test = exprData_getSingle (t->edata);
7570
7571       if (!exprNode_isError (b) && exprNode_isDefined (test))
7572         {
7573           if (context_maybeSet (FLG_INFLOOPS)
7574               || context_maybeSet (FLG_INFLOOPSUNCON))
7575             {
7576               /*
7577               ** check that some variable in the predicate is set by the body
7578               ** if the predicate uses any variables
7579               */
7580               
7581               checkInfiniteLoop (test, b);
7582             }
7583
7584           exprNode_mergeUSs (ret, b);
7585
7586           if (exprNode_isDefined (b))
7587             {
7588               ret->exitCode = exitkind_makeConditional (b->exitCode);
7589             }
7590         }
7591     }
7592   
7593   ret->edata = exprData_makePair (t, b);
7594   ret->kind = XPR_WHILE;
7595
7596   if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7597     {
7598       voptgenerror
7599         (FLG_ALWAYSEXITS,
7600          message ("Predicate always exits: %s", exprNode_unparse (t)),
7601          exprNode_loc (t));
7602     }
7603
7604   ret->exitCode = XK_NEVERESCAPE;
7605
7606   /*
7607   ** If loop is infinite, and there is no break inside, 
7608   ** exit code is never reach. 
7609   */
7610
7611   if (exprNode_knownIntValue (t))
7612     {
7613       if (!exprNode_isZero (t)) 
7614         {
7615           if (exprNode_isDefined (b)) 
7616             {
7617               if (!b->canBreak) 
7618                 {
7619                   /* Really, it means never reached. */
7620                   ret->exitCode = XK_MUSTEXIT;
7621                 }
7622             }
7623         }
7624     } 
7625   else 
7626     {
7627       ;
7628     }
7629
7630   ret->canBreak = FALSE;
7631   ret->mustBreak = FALSE;
7632
7633   return ret; 
7634 }
7635
7636 /*
7637 ** do { b } while (t);
7638 ** 
7639 ** note: body passed as first argument 
7640 */
7641
7642 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7643 {
7644   exprNode ret;
7645
7646   DPRINTF (("Do while: %s / %s",
7647             exprNode_unparse (b), exprNode_unparse (t)));
7648
7649   if (exprNode_isError (t))
7650     {
7651       if (exprNode_isError (b))
7652         {
7653           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7654         }
7655       else
7656         {
7657           ret = exprNode_createPartialCopy (b);
7658
7659           ret->exitCode = exitkind_makeConditional (b->exitCode);
7660           exprNode_checkUse (ret, b->sref, b->loc);
7661           ret->exitCode = b->exitCode;
7662           ret->canBreak = b->canBreak;
7663           ret->mustBreak = FALSE;
7664         }
7665     }
7666   else
7667     {
7668       DPRINTF (("Do while: %s / %s",
7669                 exitkind_unparse (t->exitCode),
7670                 exitkind_unparse (b->exitCode)));
7671
7672       ret = exprNode_createPartialCopy (t);
7673       exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7674       
7675       if (!exprNode_isError (b)) 
7676         {
7677           /*
7678           ** forgot the copy's --- why wasn't this detected??
7679           */
7680
7681           ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7682           ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7683           ret->uses = sRefSet_copyInto (ret->uses, b->uses);  
7684
7685           /* left this out --- causes and aliasing bug (infinite loop)
7686              should be detected?? */
7687
7688           exprNode_checkUse (ret, b->sref, b->loc);
7689           exprNode_mergeUSs (ret, t);
7690           exprNode_checkUse (ret, t->sref, t->loc);
7691
7692           /* evans 2001-10-05: while loop can break */
7693           ret->exitCode = exitkind_makeConditional (b->exitCode);
7694
7695           DPRINTF (("Do while: %s",
7696                     exitkind_unparse (ret->exitCode)));
7697
7698           ret->canBreak = b->canBreak;
7699
7700           /* Always FALSE for doWhile loops - break's when test is false */
7701           ret->mustBreak = FALSE; /* b->mustBreak; */
7702         }
7703     }
7704   
7705   context_exitDoWhileClause (t);
7706
7707   ret->kind = XPR_DOWHILE;
7708   ret->edata = exprData_makePair (t, b);
7709   return ret;
7710 }
7711
7712 bool exprNode_loopMustExec (exprNode forPred)
7713 {
7714   /*
7715   ** Returns true if it is obvious that the loop always executes at least once
7716   **
7717   ** For now, we only identify the most obvious cases.  Should be true anytime
7718   ** we can prove init => !test.
7719   */
7720
7721   if (exprNode_isDefined (forPred))
7722     {
7723       exprNode init, test, inc;
7724       exprData edata;
7725
7726       llassert (forPred->kind == XPR_FORPRED);
7727       
7728       edata = forPred->edata;
7729       init = exprData_getTripleInit (edata);
7730       test = exprData_getTripleTest (edata);
7731       inc = exprData_getTripleInc (edata);
7732       
7733       if (exprNode_isAssign (init))
7734         {
7735           exprNode loopVar = exprData_getOpA (init->edata);
7736           exprNode loopInit = exprData_getOpB (init->edata);
7737
7738           if (exprNode_isDefined (test) && test->kind == XPR_OP)
7739             {
7740               exprNode testVar = exprData_getOpA (test->edata);
7741               exprNode testVal = exprData_getOpB (test->edata);
7742               lltok comp = exprData_getOpTok (test->edata);
7743               int opid = lltok_getTok (comp);
7744
7745               DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7746                         exprNode_unparse (testVar)));
7747               
7748               if (exprNode_sameStorage (loopVar, testVar))
7749                 {
7750                   multiVal valinit = exprNode_getValue (loopInit);
7751                   multiVal valtest = exprNode_getValue (testVal);
7752
7753                   DPRINTF (("Values: %s / %s", multiVal_unparse (valinit), 
7754                             multiVal_unparse (valtest)));
7755
7756                   if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7757                     {
7758                       long v1 = multiVal_forceInt (valinit);
7759                       long v2 = multiVal_forceInt (valtest);
7760
7761                       DPRINTF (("Here: %ld %ld", v1, v2));
7762                       
7763                       if ((opid == EQ_OP && v1 < v2)
7764                           || (opid == NE_OP && v1 != v2)
7765                           || (opid == TLT && v1 <= v2)
7766                           || (opid == TGT && v1 >= v2)
7767                           || (opid == LE_OP && v1 < v2)
7768                           || (opid == GE_OP && v1 > v2))
7769                         {
7770                           DPRINTF (("mustexec if inc"));
7771                           return TRUE;
7772                         }
7773                     }
7774                 }
7775             }
7776         }
7777     }
7778
7779   DPRINTF (("loop must exec: FALSE"));
7780   return FALSE;
7781 }
7782
7783 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7784 {
7785   exprNode ret;
7786   bool emptyErr = FALSE;
7787
7788   if (context_maybeSet (FLG_FOREMPTY))
7789     {
7790       if (exprNode_isEmptyStatement (body))
7791         {
7792           emptyErr = optgenerror 
7793             (FLG_FOREMPTY,
7794              cstring_makeLiteral
7795              ("Body of for statement is empty"),
7796              exprNode_loc (body));
7797         }
7798     }
7799
7800   if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7801     {
7802       if (exprNode_isDefined (body)
7803           && !exprNode_isBlock (body))
7804         {
7805           if (context_inIterDef ()
7806               && (body->kind == XPR_STMTLIST
7807                   || body->kind == XPR_TOK))
7808             {
7809               ; /* no error */
7810             }
7811           else
7812             {
7813               voptgenerror (FLG_FORBLOCK,
7814                             message
7815                             ("Body of for statement is not a block: %s",
7816                              exprNode_unparse (body)),
7817                             exprNode_loc (body));
7818             }
7819         }
7820     }
7821
7822   /*
7823   ** for ud purposes:  (alreadly) init -> test -> (now) LOOP: body + inc + test
7824   */
7825
7826   if (exprNode_isError (body))
7827     {
7828       ret = exprNode_createPartialCopy (inc);
7829     }
7830   else
7831     {
7832       ret = exprNode_createPartialCopy (body);
7833       
7834       ret->exitCode = exitkind_makeConditional (body->exitCode);
7835
7836       exprNode_mergeUSs (inc, body);
7837       
7838       if (exprNode_isDefined (inc))
7839         {
7840           exprNode tmp;
7841
7842           context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7843           
7844           tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7845           exprNode_freeShallow (tmp); 
7846
7847           context_clearMessageAnnote ();
7848           context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7849
7850           tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7851           exprNode_freeShallow (tmp);
7852
7853           context_clearMessageAnnote ();
7854
7855           ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7856           ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7857           ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7858         }
7859     }
7860
7861   ret->kind = XPR_FOR;
7862   ret->edata = exprData_makePair (inc, body);
7863
7864   if (exprNode_isDefined (inc)) {
7865     exprNode test = exprData_getTripleTest (inc->edata);
7866
7867     if (exprNode_isUndefined (test)) {
7868       if (exprNode_isDefined (body)) {
7869         if (!body->canBreak) {
7870           /* Really, it means never reached. */
7871           ret->exitCode = XK_MUSTEXIT;
7872         }
7873       }
7874     }
7875   }
7876
7877   return (ret);
7878 }
7879
7880 /*
7881 ** for (init; test; inc)
7882 ** ==>
7883 ** init;
7884 ** while (test) { body; inc; } 
7885 **
7886 ** Now: check use of init (may set vars for test)
7887 **      check use of test
7888 **      no checks on inc
7889 _*/
7890
7891 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7892 {
7893   exprNode test;
7894
7895   if (exprNode_isError (pred)) return guardSet_undefined;
7896
7897   llassert (pred->kind == XPR_FORPRED);
7898
7899   test = exprData_getTripleTest (pred->edata);
7900
7901   if (!exprNode_isError (test))
7902     {
7903       return (test->guards);
7904     }
7905
7906   return guardSet_undefined;
7907 }
7908
7909 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7910 {
7911   exprNode ret = exprNode_createSemiCopy (test);
7912
7913   if (exprNode_isDefined (test))
7914     {
7915       exprNode_copySets (ret, test);
7916       exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7917       exprNode_checkUse (ret, test->sref, test->loc);
7918       
7919       exprNode_produceGuards (test);
7920       
7921       ret->guards = guardSet_copy (test->guards);
7922     }
7923
7924   ret->edata = exprData_makeSingle (test);
7925   ret->kind = XPR_WHILEPRED;
7926   return ret;
7927 }
7928
7929 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test, 
7930                            /*@only@*/ exprNode inc)
7931 {
7932   exprNode ret;
7933   
7934   /*
7935   ** for ud purposes:  init -> test -> LOOP: [ body, inc ]
7936   */
7937   
7938   exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7939
7940   if (!exprNode_isError (inc)) 
7941     {
7942       ret = exprNode_createPartialCopy (inc);
7943     }
7944   else 
7945     {
7946       if (!exprNode_isError (init)) 
7947         {
7948           ret = exprNode_createPartialCopy (init);
7949         }
7950       else if (!exprNode_isError (test)) 
7951         {
7952           ret = exprNode_createPartialCopy (test);
7953         }
7954       else 
7955         {
7956           ret = exprNode_createUnknown ();
7957         }
7958     }
7959
7960   exprNode_mergeUSs (ret, init);
7961
7962   if (exprNode_isDefined (init))
7963     {
7964       exprNode_checkUse (ret, init->sref, init->loc);
7965     }
7966
7967   exprNode_mergeUSs (ret, test);
7968
7969   if (exprNode_isDefined (test))
7970     {
7971       exprNode_checkUse (ret, test->sref, test->loc);
7972     }
7973
7974   ret->kind = XPR_FORPRED;
7975   ret->edata = exprData_makeFor (init, test, inc); 
7976   return (ret);
7977 }
7978
7979 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7980 {
7981   exprNode ret = exprNode_createUnknown ();
7982
7983   if (context_inMacro ())
7984     {
7985       voptgenerror (FLG_MACROSTMT,
7986                     message ("Macro %s uses goto (not functional)", 
7987                              context_inFunctionName ()),
7988                     g_currentloc);
7989     }
7990   
7991   ret->kind = XPR_GOTO;
7992   ret->edata = exprData_makeLiteral (label);
7993   ret->mustBreak = TRUE;
7994   ret->exitCode = XK_GOTO;
7995   ret->canBreak = TRUE;
7996   return ret;
7997 }
7998
7999 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
8000 {
8001   exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
8002
8003   ret->kind = XPR_CONTINUE;
8004   ret->edata = exprData_makeTok (l);
8005   ret->canBreak = TRUE;
8006   ret->mustBreak = TRUE;
8007
8008   if (qcontinue == QSAFEBREAK)
8009     {
8010       ; /* no checking */
8011     }
8012   else if (qcontinue == QINNERCONTINUE)
8013     {
8014       if (!context_inDeepLoop ())
8015         {
8016           voptgenerror 
8017             (FLG_LOOPLOOPCONTINUE,
8018              cstring_makeLiteral ("Continue statement marked with innercontinue "
8019                                   "is not inside a nested loop"),
8020              exprNode_loc (ret));
8021         }
8022     }
8023   else if (qcontinue == BADTOK)
8024     {
8025       if (context_inDeepLoop ())
8026         {
8027           voptgenerror 
8028             (FLG_LOOPLOOPCONTINUE,
8029              cstring_makeLiteral ("Continue statement in nested loop"),
8030              exprNode_loc (ret));
8031         }
8032     }
8033   else
8034     {
8035       llbuglit ("exprNode_continue: bad qcontinue");
8036     }
8037
8038   return ret;
8039 }
8040
8041 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
8042 {
8043   exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
8044   clause breakClause = context_breakClause ();
8045   
8046   ret->kind = XPR_BREAK;
8047   ret->edata = exprData_makeTok (l);
8048   ret->canBreak = TRUE;
8049   ret->mustBreak = TRUE;
8050   
8051   if (breakClause == NOCLAUSE)
8052     {
8053       voptgenerror 
8054         (FLG_SYNTAX,
8055          cstring_makeLiteral ("Break not inside while, for or switch statement"),
8056          exprNode_loc (ret));
8057     }
8058   else
8059     {
8060       if (bqual != BADTOK)
8061         {
8062           switch (bqual)
8063             {
8064             case QSAFEBREAK:
8065               break;
8066             case QINNERBREAK:
8067               if (breakClause == SWITCHCLAUSE)
8068                 {
8069                   if (!context_inDeepSwitch ())
8070                     {
8071                       voptgenerror (FLG_SYNTAX,
8072                                     cstring_makeLiteral 
8073                                     ("Break preceded by innerbreak is not in a deep switch"),
8074                                     exprNode_loc (ret));
8075                     }
8076                 }
8077               else 
8078                 {
8079                   if (!context_inDeepLoop ())
8080                     {
8081                       voptgenerror (FLG_SYNTAX,
8082                                     cstring_makeLiteral 
8083                                     ("Break preceded by innerbreak is not in a deep loop"),
8084                                     exprNode_loc (ret));
8085                     }
8086                 }
8087               break;
8088             case QLOOPBREAK:
8089               if (breakClause == SWITCHCLAUSE)
8090                 {
8091                   voptgenerror (FLG_SYNTAX,
8092                                 cstring_makeLiteral 
8093                                 ("Break preceded by loopbreak is breaking a switch"),
8094                                 exprNode_loc (ret));
8095                 }
8096               break;
8097             case QSWITCHBREAK:
8098               if (breakClause != SWITCHCLAUSE)
8099                 {
8100                   voptgenerror 
8101                     (FLG_SYNTAX,
8102                      message ("Break preceded by switchbreak is breaking %s",
8103                               cstring_makeLiteralTemp 
8104                               ((breakClause == WHILECLAUSE
8105                                 || breakClause == DOWHILECLAUSE) ? "a while loop"
8106                                : (breakClause == FORCLAUSE) ? "a for loop"
8107                                : (breakClause == ITERCLAUSE) ? "an iterator"
8108                                : "<error loop>")),
8109                      exprNode_loc (ret));
8110                 }
8111               break;
8112             BADDEFAULT;
8113             }
8114         }
8115       else
8116         {
8117           if (breakClause == SWITCHCLAUSE)
8118             {
8119               clause nextBreakClause = context_nextBreakClause ();
8120
8121               switch (nextBreakClause)
8122                 {
8123                 case NOCLAUSE: break;
8124                 case WHILECLAUSE:
8125                 case DOWHILECLAUSE:
8126                 case FORCLAUSE:
8127                 case ITERCLAUSE:
8128                   voptgenerror 
8129                     (FLG_LOOPSWITCHBREAK,
8130                      cstring_makeLiteral ("Break statement in switch inside loop"),
8131                      exprNode_loc (ret));
8132                   break;
8133                 case SWITCHCLAUSE:
8134                   voptgenerror 
8135                     (FLG_SWITCHSWITCHBREAK,
8136                      cstring_makeLiteral ("Break statement in switch inside switch"),
8137                      exprNode_loc (ret));
8138                   break;
8139                 BADDEFAULT;
8140                 }
8141             }
8142           else
8143             {
8144               if (context_inDeepLoop ())
8145                 {
8146                   voptgenerror 
8147                     (FLG_LOOPLOOPBREAK,
8148                      cstring_makeLiteral ("Break statement in nested loop"),
8149                      exprNode_loc (ret));
8150                 }
8151               else 
8152                 {
8153                   if (context_inDeepLoopSwitch ())
8154                     {
8155                       voptgenerror 
8156                         (FLG_SWITCHLOOPBREAK,
8157                          cstring_makeLiteral ("Break statement in loop inside switch"),
8158                          exprNode_loc (ret));
8159                     }
8160                 }
8161             }
8162         }
8163     }
8164
8165   return ret;
8166 }
8167
8168 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
8169 {
8170   fileloc loc = lltok_getLoc (t);
8171   exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
8172   
8173   context_returnFunction ();
8174   exprChecks_checkNullReturn (loc);
8175
8176   ret->kind = XPR_NULLRETURN;
8177   ret->edata = exprData_makeTok (t);
8178   ret->exitCode = XK_MUSTRETURN;
8179   return ret;
8180 }
8181
8182 exprNode exprNode_return (/*@only@*/ exprNode e)
8183 {
8184   exprNode ret;
8185   
8186   if (exprNode_isError (e))
8187     {
8188       ret = exprNode_createUnknown ();
8189     }
8190   else
8191     {
8192       ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
8193
8194       exprNode_checkUse (ret, e->sref, e->loc);
8195       exprNode_checkReturn (e);
8196     }
8197
8198   context_returnFunction ();
8199   ret->kind = XPR_RETURN;
8200   ret->edata = exprData_makeSingle (e);
8201   ret->exitCode = XK_MUSTRETURN;
8202
8203   return (ret);
8204 }
8205
8206 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
8207 {
8208   exprNode ret;
8209
8210   if (exprNode_isError (e1)) 
8211     {
8212       if (exprNode_isError (e2))
8213         {
8214           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8215         }
8216       else
8217         {
8218           ret = exprNode_createPartialCopy (e2);
8219           exprNode_checkUse (ret, e2->sref, e2->loc);
8220           ret->sref = e2->sref;
8221         }
8222     }
8223   else
8224     {
8225       ret = exprNode_createPartialCopy (e1);
8226
8227       exprNode_checkUse (ret, e1->sref, e1->loc);
8228
8229       if (!exprNode_isError (e2))
8230         {
8231           exprNode_mergeUSs (ret, e2);
8232           exprNode_checkUse (ret, e2->sref, e2->loc);
8233           ret->sref = e2->sref;
8234         }
8235     }
8236
8237   ret->kind = XPR_COMMA;
8238   ret->edata = exprData_makePair (e1, e2);
8239   
8240   if (exprNode_isDefined (e1))
8241     {
8242       if (exprNode_isDefined (e2))
8243         {
8244           ret->typ = e2->typ; 
8245
8246           if (exprNode_mustEscape (e1) || e1->mustBreak)
8247             {
8248               voptgenerror 
8249                 (FLG_UNREACHABLE,
8250                  message ("Second clause of comma expression is unreachable: %s",
8251                           exprNode_unparse (e2)), 
8252                  exprNode_loc (e2));
8253             }
8254           
8255           ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8256           ret->mustBreak = e1->mustBreak || e2->mustBreak;
8257           ret->canBreak = e1->canBreak || e2->canBreak;
8258         }
8259       else
8260         {
8261           if (exprNode_mustEscape (e1) || e1->mustBreak)
8262             {
8263               voptgenerror 
8264                 (FLG_UNREACHABLE,
8265                  message ("Second clause of comma expression is unreachable: %s",
8266                           exprNode_unparse (e2)), 
8267                  exprNode_loc (e2));
8268             }
8269           
8270           ret->exitCode = e1->exitCode;
8271           ret->canBreak = e1->canBreak;
8272         }
8273     }
8274   else
8275     {
8276       if (exprNode_isDefined (e2))
8277         {
8278           ret->exitCode = e2->exitCode;
8279           ret->mustBreak = e2->mustBreak;
8280           ret->canBreak = e2->canBreak;
8281         }
8282     }
8283
8284   return (ret);
8285 }
8286
8287 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8288 {
8289   ctype t1 = exprNode_getType (el);
8290   ctype t2 = exprNode_getType (val);
8291   bool hasError = FALSE;
8292   
8293   DPRINTF (("Check one init: %s / %s",
8294             exprNode_unparse (el),
8295             exprNode_unparse (val)));
8296
8297   if (ctype_isUnknown (t1))
8298     {
8299       voptgenerror (FLG_IMPTYPE,
8300                     message ("Variable has unknown (implicitly int) type: %s",
8301                              exprNode_unparse (el)),
8302                     el->loc);
8303       
8304       t1 = ctype_int;
8305       el->typ = ctype_int;
8306     }
8307
8308   if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8309     {
8310       exprNodeList vals = exprData_getArgs (val->edata);
8311       
8312       DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8313       DPRINTF (("Type: %s", ctype_unparse (t1)));
8314
8315       if (ctype_isRealAP (t1))
8316         {
8317           int i = 0;
8318           int nerrors = 0;
8319
8320           if (ctype_isFixedArray (t1))
8321             {
8322               size_t nelements = ctype_getArraySize (t1);
8323               
8324               DPRINTF (("Checked array: %s / %d",
8325                         ctype_unparse (t1), nelements));
8326
8327               if (exprNode_isStringLiteral (val))
8328                 {
8329                   exprNode_checkStringLiteralLength (t1, val);
8330                 }
8331               else
8332                 {
8333                   if (exprNodeList_size (vals) != size_toInt (nelements))
8334                     {
8335                       hasError = optgenerror 
8336                         (exprNodeList_size (vals) > size_toInt (nelements) 
8337                          ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8338                          message ("Initializer block for "
8339                                   "%s has %d element%&, but declared as %s: %q",
8340                                   exprNode_unparse (el),
8341                                   exprNodeList_size (vals),
8342                                   ctype_unparse (t1),
8343                                   exprNodeList_unparse (vals)),
8344                          val->loc);       
8345                     }
8346                 }
8347             }
8348           
8349           exprNodeList_elements (vals, oneval)
8350             {
8351               cstring istring = message ("%d", i);
8352               exprNode newel =
8353                 exprNode_arrayFetch 
8354                   (exprNode_fakeCopy (el),
8355                    exprNode_numLiteral (ctype_int, istring,
8356                                         fileloc_copy (el->loc), i));
8357               
8358               if (exprNode_isDefined (newel))
8359                 {
8360                   if (exprNodeList_size (vals) == 1
8361                       && ctype_isString (exprNode_getType (oneval))
8362                       && ctype_isChar (exprNode_getType (newel)))
8363                     {
8364                       exprNode_freeIniter (newel);
8365                     }
8366                   else
8367                     {
8368                       if (exprNode_checkOneInit (newel, oneval))
8369                         {
8370                           hasError = TRUE;
8371                           nerrors++;
8372                           
8373                           if (nerrors > 3 && exprNodeList_size (vals) > 6)
8374                             {
8375                               llgenmsg 
8376                                 (message ("Additional initialization errors "
8377                                           "for %s not reported",
8378                                           exprNode_unparse (el)),
8379                                  exprNode_loc (el));
8380                               exprNode_freeIniter (newel);
8381                               break;
8382                             }
8383                           else
8384                             {
8385                               exprNode_freeIniter (newel);
8386                             }
8387                         }
8388                       else
8389                         {
8390                           exprNode_freeIniter (newel);
8391                         }
8392                     }
8393                 }
8394
8395               cstring_free (istring);
8396               i++;
8397               /*@-branchstate@*/ 
8398             } end_exprNodeList_elements;
8399           /*@=branchstate@*/
8400         }
8401       else if (ctype_isStruct (ctype_realType (t1)))
8402         {
8403           uentryList fields = ctype_getFields (t1);
8404           int i = 0;
8405
8406           if (uentryList_size (fields) != exprNodeList_size (vals))
8407             {
8408               if (uentryList_size (fields) > exprNodeList_size (vals))
8409                 {
8410                   hasError = optgenerror 
8411                     (FLG_FULLINITBLOCK,
8412                      message ("Initializer block for "
8413                               "%s has %d field%&, but %s has %d field%&: %q",
8414                               exprNode_unparse (el),
8415                               exprNodeList_size (vals),
8416                               ctype_unparse (t1),
8417                               uentryList_size (fields),
8418                               exprNodeList_unparse (vals)),
8419                      val->loc);   
8420                 }
8421               else
8422                 {
8423                   hasError = optgenerror 
8424                     (FLG_TYPE,
8425                      message ("Initializer block for "
8426                               "%s has %d field%&, but %s has %d field%&: %q",
8427                               exprNode_unparse (el),
8428                               exprNodeList_size (vals),
8429                               ctype_unparse (t1),
8430                               uentryList_size (fields),
8431                               exprNodeList_unparse (vals)),
8432                      val->loc);   
8433                 }
8434             }
8435           else
8436             {
8437               exprNodeList_elements (vals, oneval)
8438                 {
8439                   uentry thisfield = uentryList_getN (fields, i);
8440                   exprNode newel =
8441                     exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8442                                              exprNode_loc (el),
8443                                              uentry_getName (thisfield));
8444
8445                   if (exprNode_isDefined (newel))
8446                     {
8447                       if (exprNode_checkOneInit (newel, oneval))
8448                         {
8449                           hasError = TRUE;
8450                         }
8451
8452                       exprNode_freeIniter (newel);
8453                     }
8454
8455                   i++;
8456                 } end_exprNodeList_elements;
8457             }
8458         }
8459       /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8460       else if (ctype_isUnion (ctype_realType (t1)))
8461         {
8462           uentryList fields = ctype_getFields (t1);
8463           int i = 0;
8464
8465           /*
8466           ** Union initializers set the first member always.
8467           */
8468
8469           DPRINTF (("Union initializer: %s / %s",
8470                     exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8471
8472           if (exprNodeList_size (vals) != 1)
8473             {
8474               hasError = optgenerror 
8475                 (FLG_TYPE,
8476                  message ("Initializer block for union "
8477                           "%s has %d elements, union initializers should have one element: %q",
8478                           exprNode_unparse (el),
8479                           exprNodeList_size (vals),
8480                           exprNodeList_unparse (vals)),
8481                  val->loc);       
8482             }
8483           else
8484             {
8485               exprNode oneval = exprNodeList_head (vals);
8486               uentry thisfield = uentryList_getN (fields, i);
8487               exprNode newel =
8488                 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8489                                          exprNode_loc (el),
8490                                          uentry_getName (thisfield));
8491               
8492               if (exprNode_isDefined (newel))
8493                 {
8494                   if (exprNode_checkOneInit (newel, oneval))
8495                     {
8496                       hasError = TRUE;
8497                     }
8498                   
8499                   exprNode_freeIniter (newel);
8500                 }
8501             }
8502         }
8503       else
8504         {
8505           hasError = optgenerror 
8506             (FLG_TYPE,
8507              message ("Initializer block used for "
8508                       "%s where %t is expected: %s",
8509                       exprNode_unparse (el), t1, exprNode_unparse (val)),
8510              val->loc);   
8511         }
8512     }
8513   else
8514     {
8515       if (exprNode_isDefined (val))
8516         {
8517           doAssign (el, val, TRUE);
8518           
8519           if (!exprNode_matchType (t1, val))
8520             {
8521               hasError = gentypeerror 
8522                 (t1, val, t2, el,
8523                  message ("Initial value of %s is type %t, "
8524                           "expects %t: %s",
8525                           exprNode_unparse (el),
8526                           t2, t1, exprNode_unparse (val)),
8527                  val->loc);
8528             }
8529         }
8530     }
8531
8532   return hasError;
8533 }
8534
8535 static /*@notnull@*/ exprNode 
8536 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8537 {
8538   exprNode ret;
8539
8540   DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8541
8542   if (usymtab_exists (idDecl_observeId (t)))
8543     {
8544       uentry ue = usymtab_lookup (idDecl_observeId (t));
8545       ret = exprNode_createId (ue);
8546     }
8547   else
8548     {
8549       uentry ue;
8550
8551       DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8552
8553       ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8554       ret = exprNode_fromIdentifierAux (ue);
8555
8556       /*
8557       ** No error - this happens in old style declarations:
8558
8559       voptgenerror
8560         (FLG_UNRECOG,
8561          message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8562          g_currentloc);
8563
8564       ** 
8565       */
8566     }
8567
8568   exprData_free (ret->edata, ret->kind); 
8569   ret->edata = exprData_undefined;
8570   ret->exitCode = XK_NEVERESCAPE;
8571   ret->mustBreak = FALSE;
8572   ret->kind = XPR_INIT;
8573   return ret;
8574 }
8575   
8576 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8577 {
8578   exprNode ret = exprNode_makeInitializationAux (t);
8579   llassert (ret->edata == exprData_undefined);
8580   ret->edata = exprData_makeInit (t, exprNode_undefined);
8581   return ret;
8582 }
8583
8584 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8585                                       /*@only@*/ exprNode e)
8586 {
8587   uentry ue = usymtab_lookup (idDecl_observeId (t));
8588   exprNode ret = exprNode_makeInitializationAux (t);
8589   fileloc loc = exprNode_loc (e);
8590
8591   DPRINTF (("initialization: %s = %s", idDecl_unparse (t), exprNode_unparse (e)));
8592
8593   if (exprNode_isError (e)) 
8594     {
8595       e = exprNode_createUnknown ();
8596       /* error: assume initializer is defined */
8597       sRef_setDefined (ret->sref, g_currentloc); 
8598       ret->edata = exprData_makeInit (t, e);
8599     }
8600   else
8601     {
8602       ctype ct = ctype_realishType (ret->typ);
8603
8604       /*
8605       ** evs - 9 Apr 1995
8606       **
8607       ** was addSafeUse --- what's the problem?
8608       **
8609       **   int x = 3, y = x ?
8610       */
8611
8612       exprData_free (ret->edata, ret->kind);
8613       ret->edata = exprData_makeInit (t, e);
8614       DPRINTF (("ret: %s", exprNode_unparse (ret)));
8615
8616       exprNode_checkUse (ret, e->sref, e->loc);
8617       
8618       if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8619         {
8620           exprNode lhs = exprNode_createId (ue);
8621
8622           /*
8623           ** static storage should be undefined before initializing
8624           */
8625
8626           if (uentry_isStatic (ue))
8627             {
8628               sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8629             }
8630           
8631           (void) exprNode_checkOneInit (lhs, e);
8632
8633           if (uentry_isStatic (ue))
8634             {
8635               sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8636             }
8637
8638           exprNode_free (lhs);
8639         }
8640       else
8641         {
8642           if (!exprNode_matchType (ct, e))
8643             {
8644               if (exprNode_isZero (e) && ctype_isArrayPtr (ct)) 
8645                 {
8646                   ;
8647                 }
8648               else
8649                 {
8650                   (void) gentypeerror 
8651                     (exprNode_getType (e), e, exprNode_getType (ret), ret,
8652                      message 
8653                      ("Variable %q initialized to type %t, expects %t: %s",
8654                       uentry_getName (ue), exprNode_getType (e), 
8655                       exprNode_getType (ret),
8656                       exprNode_unparse (e)),
8657                      e->loc);
8658                 }
8659             }
8660         }
8661       
8662       if (uentry_isStatic (ue))
8663         {
8664           sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8665         }
8666
8667       if (exprNode_isStringLiteral (e)
8668           && (ctype_isArray (ct))
8669           && (ctype_isChar (ctype_realType (ctype_baseArrayPtr (ct)))))
8670         {
8671           /*
8672           ** If t is a char [], the literal is copied.
8673           */
8674
8675           exprNode_checkStringLiteralLength (ct, e);
8676           sRef_setDefState (ret->sref, SS_DEFINED, e->loc);
8677           ret->val = multiVal_copy (e->val);
8678
8679           sRef_setNullTerminatedState (ret->sref);
8680           
8681           if (multiVal_isDefined (e->val))
8682             {
8683               cstring slit = multiVal_forceString (e->val);
8684               sRef_setLen (ret->sref, size_toInt (cstring_length (slit) + 1));
8685             }
8686
8687           if (ctype_isFixedArray (ct))
8688             {
8689               sRef_setSize (ret->sref, size_toInt (ctype_getArraySize (ct)));
8690             }
8691         }
8692       else
8693         {
8694           doAssign (ret, e, TRUE);
8695         }
8696
8697       if (uentry_isStatic (ue))
8698         {
8699           sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8700         }
8701     }
8702   
8703   if (context_inIterDef ())
8704     {
8705       /* should check if it is yield */
8706       uentry_setUsed (ue, loc);
8707     }
8708   else
8709     {
8710       ;
8711     }
8712
8713   exprNode_mergeUSs (ret, e);
8714   DPRINTF (("Ret: %s %p %p",
8715             exprNode_unparse (ret),
8716             ret->requiresConstraints,
8717             ret->ensuresConstraints));
8718
8719   DPRINTF (("Ret: %s %s %s",
8720             exprNode_unparse (ret),
8721             constraintList_unparse (ret->requiresConstraints),
8722             constraintList_unparse (ret->ensuresConstraints)));
8723   return ret;
8724 }
8725   
8726 exprNode exprNode_iter (/*@observer@*/ uentry name,
8727                         /*@only@*/ exprNodeList alist, 
8728                         /*@only@*/ exprNode body,
8729                         /*@observer@*/ uentry end)
8730 {
8731   exprNode ret;
8732   cstring iname;
8733
8734   llassert (uentry_isValid (name));
8735
8736   uentry_setUsed (name, exprNode_loc (body));
8737
8738   ret = exprNode_createPartialCopy (body);
8739   iname = uentry_getName (name);
8740
8741   if (uentry_isInvalid (end))
8742     {
8743       llerror (FLG_ITERBALANCE,
8744                message ("Iter %s not balanced with end_%s", iname, iname));
8745     }
8746   else
8747     {
8748       cstring ename = uentry_getName (end);
8749
8750       if (!cstring_equalPrefixLit (ename, "end_"))
8751         {
8752           llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s", 
8753                                       iname, iname, ename));
8754         }
8755       else
8756         {
8757           if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8758             {
8759               llerror (FLG_ITERBALANCE, 
8760                        message ("Iter %s not balanced with end_%s: %s", 
8761                                 iname, iname, ename));
8762             }
8763         }
8764
8765       cstring_free (ename);
8766     }
8767
8768   context_exitIterClause (body);
8769   
8770   ret->kind = XPR_ITER;
8771   ret->edata = exprData_makeIter (name, alist, body, end);
8772
8773   if (uentry_isIter (name))
8774     {
8775       (void) checkArgsReal (name, body, 
8776                             uentry_getParams (name), alist, TRUE, ret);
8777     }
8778
8779   cstring_free (iname);
8780
8781   return ret;
8782 }
8783
8784 exprNode
8785 exprNode_iterNewId (/*@only@*/ cstring s)
8786 {
8787   exprNode e = exprNode_new ();
8788   uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8789
8790   llassert (processingIterVars ());
8791
8792   e->loc = context_getSaveLocation ();
8793
8794   if (fileloc_isUndefined (e->loc))
8795     {
8796       fileloc_free (e->loc);
8797       e->loc = fileloc_copy (g_currentloc);
8798     }
8799
8800   e->uses = sRefSet_new ();
8801   e->sets = sRefSet_new ();
8802   e->msets = sRefSet_new ();
8803   e->kind = XPR_VAR;
8804   e->val = multiVal_unknown ();
8805   e->guards = guardSet_new ();
8806   e->sref = sRef_undefined;
8807   e->isJumpPoint = FALSE;
8808   e->exitCode = XK_NEVERESCAPE;
8809
8810   /*> missing fields, detected by splint <*/
8811   e->canBreak = FALSE;
8812   e->mustBreak = FALSE;
8813   e->etext = cstring_undefined;
8814
8815   if (uentry_isYield (ue))
8816     {
8817       uentry uue = uentry_makeVariable (s, uentry_getType (ue), 
8818                                         fileloc_copy (e->loc), 
8819                                         FALSE);
8820       sRef sr;
8821
8822       uue = usymtab_supEntrySrefReturn (uue);
8823
8824       sr = uentry_getSref (uue);
8825       sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8826       sr = uentry_getSref (uue);
8827       sRef_setDefined (sr, e->loc);
8828
8829       e->typ = uentry_getType (uue);      
8830       e->sref = sr;
8831       e->edata = exprData_makeId (uue);
8832       uentry_setUsed (uue, g_currentloc);
8833     }
8834   else
8835     {
8836       uentry uue;
8837
8838       sRef_setGlobalScope ();
8839       uue = uentry_makeVariableLoc (s, ctype_unknown);
8840
8841       e->typ = ctype_unknown;
8842       e->edata = exprData_makeId (uue);
8843
8844       uentry_setUsed (uue, e->loc);
8845       uentry_setHasNameError (uue); 
8846
8847       if (context_getFlag (FLG_REPEATUNRECOG))
8848         {
8849           uentry_markOwned (uue);
8850         }
8851       else
8852         {
8853           usymtab_supGlobalEntry (uue);      
8854         }
8855
8856       sRef_clearGlobalScope ();
8857
8858       voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8859                     e->loc);
8860     }
8861
8862
8863   cstring_free (s);
8864   
8865   exprNode_defineConstraints(e);
8866   return (e);
8867 }
8868
8869 exprNode
8870 exprNode_iterExpr (/*@returned@*/ exprNode e)
8871 {
8872   if (!processingIterVars ())
8873     {
8874       llcontbuglit ("checkIterParam: not in iter");
8875       return e;
8876     }
8877   
8878   if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()), 
8879                                        iterParamNo ())))
8880     {
8881       if (exprNode_isDefined (e))
8882         {
8883           if (fileloc_isDefined (e->loc))
8884             {
8885               voptgenerror
8886                 (FLG_ITERYIELD,
8887                  message ("Yield parameter is not simple identifier: %s", 
8888                           exprNode_unparse (e)),
8889                  e->loc);
8890             }
8891           else
8892             {
8893               voptgenerror
8894                 (FLG_ITERYIELD,
8895                  message ("Yield parameter is not simple identifier: %s",
8896                           exprNode_unparse (e)),
8897                  g_currentloc);
8898               
8899             }
8900         }
8901     }
8902   return e;
8903 }
8904
8905 exprNode
8906 exprNode_iterId (/*@observer@*/ uentry c)
8907 {
8908   uentry ue;
8909
8910   llassert (processingIterVars ());
8911
8912   ue = uentryList_getN (uentry_getParams (getCurrentIter ()), 
8913                         iterParamNo ());
8914
8915   if (uentry_isYield (ue))
8916     {
8917       ctype ct = uentry_getType (ue);
8918       exprNode e = exprNode_createPlain (ct);
8919       cstring name = uentry_getName (c);
8920       uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8921
8922       uentry_setUsed (ue, g_currentloc);
8923       uentry_setHasNameError (ue); 
8924       
8925       cstring_free (name);
8926       
8927       e->kind = XPR_VAR;
8928       e->edata = exprData_makeId (le);
8929       e->loc = context_getSaveLocation ();
8930       e->sref = uentry_getSref (le);
8931
8932       usymtab_supEntrySref (le);
8933
8934       if (!context_inHeader ())
8935         {
8936           if (optgenerror
8937               (FLG_ITERYIELD,
8938                message ("Yield parameter shadows local declaration: %q",
8939                         uentry_getName (c)),
8940                fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8941             {
8942               uentry_showWhereDeclared (c);
8943             }
8944         }
8945
8946       return e;
8947     }
8948
8949   return (exprNode_fromIdentifierAux (c));
8950 }
8951
8952 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8953 {
8954   exprNode ret = exprNode_create (ctype_unknown);
8955
8956   ret->kind = XPR_ITERCALL;
8957   ret->edata = exprData_makeIterCall (name, alist);
8958   
8959   if (uentry_isIter (name))
8960     {
8961       uentryList params = uentry_getParams (name);
8962
8963       if (context_inIterDef () 
8964           && uentryList_size (params) == exprNodeList_size (alist))
8965         {
8966           int i = 0;
8967           
8968           exprNodeList_elements (alist, arg)
8969             {
8970               uentry parg = uentryList_getN (params, i);
8971
8972               if (uentry_isYield (parg))
8973                 {
8974                   uentry ue = exprNode_getUentry (arg);
8975
8976                   if (uentry_isValid (ue))
8977                     {
8978                       ;
8979                     }
8980                 }
8981
8982               i++;
8983             } end_exprNodeList_elements;
8984         }
8985
8986       (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8987       checkUnspecCall (ret, params, alist);
8988     }
8989
8990   return ret;
8991 }
8992
8993 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8994 {
8995   if (exprNode_isDefined (e))
8996     {
8997       if (sRef_isInvalid (e->sref))
8998         {
8999           /*@-mods@*/
9000           e->sref = sRef_makeUnknown (); 
9001           sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
9002           /*@=mods@*/
9003           return e->sref;
9004         }
9005       else
9006         {
9007           return e->sref;
9008         }
9009     }
9010   else
9011     {
9012       return sRef_undefined;
9013     }
9014 }
9015
9016 /*@observer@*/ cstring
9017 exprNode_unparseFirst (exprNode e)
9018 {
9019   if (exprNode_isDefined (e))
9020     {
9021       cstring ret;
9022
9023       if (e->kind == XPR_STMTLIST
9024           || e->kind == XPR_COMMA || e->kind == XPR_COND)
9025         {
9026           exprNode first = exprData_getPairA (e->edata);
9027
9028           if (exprNode_isDefined (first))
9029             {
9030               return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
9031             }
9032           else
9033             {
9034               return (cstring_makeLiteralTemp ("..."));
9035             }
9036         }
9037
9038       ret = cstring_elide (exprNode_unparse (e), 20);
9039       cstring_markOwned (ret);
9040       
9041       return (ret);
9042     }
9043   else
9044     {
9045       return cstring_makeLiteralTemp ("<error>");
9046     }
9047 }
9048
9049 /*@observer@*/ cstring
9050 exprNode_unparse (/*@temp@*/ exprNode e)
9051 {
9052   if (exprNode_isError (e))
9053     {
9054       return cstring_makeLiteralTemp ("<error>");
9055     }
9056
9057   if (cstring_isDefined (e->etext))
9058     {
9059       return e->etext;
9060     }
9061   else
9062     {
9063       cstring ret = exprNode_doUnparse (e);
9064
9065       /*@-modifies@*/ /* benevolent */
9066       e->etext = ret; 
9067       /*@=modifies@*/
9068       return ret;
9069     }
9070 }
9071
9072 /*@observer@*/ fileloc
9073 exprNode_loc (exprNode e)
9074 {
9075   if (exprNode_isError (e))
9076     {
9077       return (g_currentloc);
9078     }
9079   else
9080     {
9081       return (e->loc);
9082     }
9083 }
9084
9085 /*
9086 ** executes exprNode e
9087 **    recursively rexecutes as though in original parse using
9088 **    information in e->edata
9089 */
9090
9091 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
9092 {
9093   exprNodeList ret = exprNodeList_new ();
9094
9095   exprNodeList_elements (e, current)
9096     {
9097       exprNodeList_addh (ret, exprNode_effect (current));
9098     } end_exprNodeList_elements;
9099
9100   return ret;
9101 }
9102
9103 static /*@only@*/ exprNode exprNode_effect (exprNode e) 
9104    /*@globals internalState@*/
9105 {
9106   bool innerEffect = inEffect;
9107   exprNode ret;
9108   exprData data;
9109
9110   inEffect = TRUE;
9111
9112   context_clearJustPopped ();
9113
9114   if (exprNode_isError (e))
9115     {
9116       ret = exprNode_undefined;
9117     }
9118   else
9119     {
9120       /*
9121       ** Turn off expose and dependent transfer checking.
9122       ** Need to pass exposed internal nodes,
9123       ** [ copying would be a waste! ]
9124       ** [ Actually, I think I wasted a lot more time than its worth ]
9125       ** [ trying to do this. ]
9126       */
9127
9128       /*@-exposetrans@*/
9129       /*@-observertrans@*/
9130       /*@-dependenttrans@*/
9131       
9132       data = e->edata;
9133       
9134       switch (e->kind)
9135         {
9136         case XPR_PARENS: 
9137           ret = exprNode_addParens (exprData_getUopTok (data), 
9138                                     exprNode_effect (exprData_getUopNode (data)));
9139           break;
9140         case XPR_ASSIGN:
9141           ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)), 
9142                                  exprNode_effect (exprData_getOpB (data)), 
9143                                  exprData_getOpTok (data));
9144           break;
9145         case XPR_INITBLOCK:
9146           ret = exprNode_undefined;
9147           break;
9148         case XPR_CALL:
9149           ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
9150                                        exprNodeList_effect (exprData_getArgs (data)));
9151           break;
9152         case XPR_EMPTY:
9153           ret = e;
9154           break;
9155
9156         case XPR_LABEL:
9157           ret = e;
9158           break;
9159
9160         case XPR_CONST:
9161         case XPR_VAR:
9162           {
9163             cstring id = exprData_getId (data);
9164             uentry ue = usymtab_lookupSafe (id);
9165
9166             ret = exprNode_fromIdentifierAux (ue);
9167             ret->loc = fileloc_update (ret->loc, e->loc);
9168             break;
9169           }
9170         case XPR_BODY:
9171           ret = e;
9172           break;
9173         case XPR_FETCH:
9174           ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)), 
9175                                      exprNode_effect (exprData_getPairB (data)));
9176           break;
9177         case XPR_OP:
9178           /*
9179           ** evans 2002-03-15: for && and ||, need to do the guards also
9180           **                   this is what cgrammar.y does - should be
9181           **                   able to avoid duplication, but need to
9182           **                   time with grammar productions.
9183           */
9184
9185           DPRINTF (("Effect: %s", exprNode_unparse (e)));
9186
9187           if (lltok_getTok (exprData_getOpTok (data)) == AND_OP)
9188             {
9189               exprNode e1 = exprNode_effect (exprData_getOpA (data));
9190               exprNode e2;
9191               exprNode_produceGuards (e1);
9192               context_enterAndClause (e1);
9193               e2 = exprNode_effect (exprData_getOpB (data));
9194
9195               ret = exprNode_op (e1, e2,
9196                                  exprData_getOpTok (data));
9197
9198               context_exitAndClause (ret, e2);
9199             }
9200           else if (lltok_getTok (exprData_getOpTok (data)) == OR_OP)
9201             {
9202               exprNode e1 = exprNode_effect (exprData_getOpA (data));
9203               exprNode e2;
9204               exprNode_produceGuards (e1);
9205               context_enterOrClause (e1);
9206               e2 = exprNode_effect (exprData_getOpB (data));
9207
9208               ret = exprNode_op (e1, e2,
9209                                  exprData_getOpTok (data));
9210
9211               context_exitOrClause (ret, e2);
9212             }
9213           else
9214             {
9215               ret = exprNode_op (exprNode_effect (exprData_getOpA (data)), 
9216                                  exprNode_effect (exprData_getOpB (data)), 
9217                                  exprData_getOpTok (data));
9218             }
9219           break;
9220           
9221         case XPR_POSTOP:
9222           ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)), 
9223                                  exprData_getUopTok (data));
9224           break;
9225         case XPR_PREOP:
9226           ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)), 
9227                                 exprData_getUopTok (data));
9228           break;
9229
9230         case XPR_OFFSETOF:
9231         case XPR_SIZEOFT:
9232         case XPR_SIZEOF:
9233         case XPR_ALIGNOFT:
9234         case XPR_ALIGNOF:
9235           ret = e;
9236           break;
9237           
9238         case XPR_VAARG:
9239           ret = exprNode_vaArg (exprData_getCastTok (data),
9240                                 exprNode_effect (exprData_getCastNode (data)),
9241                                 exprData_getCastType (data));
9242           break;
9243           
9244         case XPR_CAST:
9245           ret = exprNode_cast (exprData_getCastTok (data), 
9246                                exprNode_effect (exprData_getCastNode (data)), 
9247                                exprData_getCastType (data));
9248           break;
9249         case XPR_ITERCALL:
9250           ret = exprNode_iterStart (exprData_getIterCallIter (data),
9251                                     exprNodeList_effect 
9252                                     (exprData_getIterCallArgs (data)));
9253           break;
9254           
9255         case XPR_ITER:
9256           ret = exprNode_iter (exprData_getIterSname (data),
9257                                exprNodeList_effect (exprData_getIterAlist (data)),
9258                                exprNode_effect (exprData_getIterBody (data)),
9259                                exprData_getIterEname (data));
9260           break;
9261           
9262         case XPR_FOR:
9263           ret = exprNode_for (exprNode_effect (exprData_getPairA (data)), 
9264                               exprNode_effect (exprData_getPairB (data)));
9265           break;
9266           
9267         case XPR_FORPRED:
9268           ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9269                                   exprNode_effect (exprData_getTripleTest (data)),
9270                                   exprNode_effect (exprData_getTripleInc (data)));
9271           break;
9272           
9273         case XPR_TOK:
9274           ret = exprNode_createTok (exprData_getTok (data));
9275           break;
9276           
9277         case XPR_GOTO:
9278           ret = exprNode_goto (exprData_getLiteral (data));
9279           ret->loc = fileloc_update (ret->loc, e->loc);
9280           break;
9281           
9282         case XPR_CONTINUE:
9283           ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9284           break;
9285           
9286         case XPR_BREAK:
9287           ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9288           break;
9289           
9290         case XPR_RETURN:
9291           ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9292           break;
9293           
9294         case XPR_NULLRETURN:
9295           ret = exprNode_nullReturn (exprData_getTok (data));
9296           break;
9297           
9298         case XPR_COMMA:
9299           ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9300                                 exprNode_effect (exprData_getPairB (data)));
9301           break;
9302           
9303         case XPR_COND:
9304           ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9305                                exprNode_effect (exprData_getTripleTrue (data)),
9306                                exprNode_effect (exprData_getTripleFalse (data)));
9307           break;
9308         case XPR_IF:
9309           ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9310                              exprNode_effect (exprData_getPairB (data)));
9311           break;
9312           
9313         case XPR_IFELSE:
9314           ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9315                                  exprNode_effect (exprData_getTripleTrue (data)),
9316                                  exprNode_effect (exprData_getTripleFalse (data)));
9317           break;
9318         case XPR_WHILEPRED:
9319           ret = exprNode_whilePred (exprData_getSingle (data));
9320           break;
9321           
9322         case XPR_WHILE:
9323           ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9324                                 exprNode_effect (exprData_getPairB (data)));
9325           break;
9326           
9327         case XPR_DOWHILE:
9328           ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9329                                   exprNode_effect (exprData_getPairB (data)));
9330           break;
9331
9332         case XPR_BLOCK:
9333           ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9334           break;          
9335
9336         case XPR_STMT:
9337           ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9338                                     exprData_getUopTok (data));
9339           break;
9340           
9341         case XPR_STMTLIST:
9342           ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9343                                  exprNode_effect (exprData_getPairB (data)));
9344           break;
9345           
9346         case XPR_FTCASE:
9347         case XPR_CASE:
9348           ret = exprNode_caseMarker 
9349             (exprNode_effect (exprData_getSingle (data)),
9350              TRUE);
9351           break;
9352           
9353         case XPR_FTDEFAULT:
9354         case XPR_DEFAULT:
9355           ret = exprNode_createTok (exprData_getTok (data));
9356           break;
9357           
9358         case XPR_SWITCH:
9359           ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9360                                  exprNode_effect (exprData_getPairB (data)));
9361           break;
9362           
9363         case XPR_INIT:
9364           ret = exprNode_makeInitialization
9365             (exprData_getInitId (data),
9366              exprNode_effect (exprData_getInitNode (data)));
9367           break;
9368           
9369         case XPR_FACCESS:
9370           ret = exprNode_fieldAccessAux
9371             (exprNode_effect (exprData_getFieldNode (data)),
9372              exprNode_loc (exprData_getFieldNode (data)),
9373              cstring_copy (exprData_getFieldName (data)));
9374           break;
9375           
9376         case XPR_ARROW:
9377           ret = exprNode_arrowAccessAux
9378             (exprNode_effect (exprData_getFieldNode (data)),
9379              exprNode_loc (exprData_getFieldNode (data)),
9380              cstring_copy (exprData_getFieldName (data)));
9381           break;
9382           
9383         case XPR_STRINGLITERAL:
9384           ret = e;
9385           break;
9386           
9387         case XPR_NUMLIT:
9388           ret = e;
9389           break;
9390
9391         case XPR_NODE:
9392           ret = e;
9393           break;
9394           /*@-branchstate@*/ 
9395         } 
9396       /*@=branchstate@*/
9397       /*@=observertrans@*/
9398       /*@=exposetrans@*/
9399       /*@=dependenttrans@*/
9400     }
9401
9402   if (!innerEffect) 
9403     {
9404       inEffect = FALSE;
9405     }
9406
9407   return ret;
9408 }
9409
9410 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9411 {
9412   cstring ret;
9413   exprData data;
9414
9415   if (exprNode_isError (e))
9416     {
9417       return cstring_undefined;
9418     }
9419
9420   data = e->edata;
9421
9422   switch (e->kind)
9423     {
9424     case XPR_PARENS: 
9425       ret = exprNode_rootVarName (exprData_getUopNode (data));
9426       break;
9427     case XPR_ASSIGN:
9428       ret = exprNode_rootVarName (exprData_getOpA (data));
9429       break;
9430     case XPR_CONST:
9431     case XPR_VAR:
9432       ret = exprData_getId (data);
9433       break;
9434     case XPR_INIT:
9435       ret = idDecl_getName (exprData_getInitId (data));
9436       break;
9437     case XPR_LABEL:
9438     case XPR_TOK:
9439     case XPR_ITERCALL:
9440     case XPR_EMPTY:
9441     case XPR_CALL:
9442     case XPR_INITBLOCK:
9443     case XPR_BODY:
9444     case XPR_FETCH:
9445     case XPR_OP:
9446     case XPR_POSTOP:
9447     case XPR_PREOP:
9448     case XPR_OFFSETOF:
9449     case XPR_ALIGNOFT:
9450     case XPR_ALIGNOF:
9451     case XPR_SIZEOFT:
9452     case XPR_SIZEOF:
9453     case XPR_VAARG:
9454     case XPR_CAST:
9455     case XPR_ITER:
9456     case XPR_FOR:
9457     case XPR_FORPRED:
9458     case XPR_BREAK:
9459     case XPR_RETURN:
9460     case XPR_NULLRETURN:
9461     case XPR_COMMA:
9462     case XPR_COND:
9463     case XPR_IF:
9464     case XPR_IFELSE:
9465     case XPR_WHILE:
9466     case XPR_WHILEPRED:
9467     case XPR_DOWHILE:
9468     case XPR_GOTO:
9469     case XPR_CONTINUE:
9470     case XPR_FTDEFAULT:
9471     case XPR_DEFAULT:
9472     case XPR_SWITCH:
9473     case XPR_FTCASE:
9474     case XPR_CASE:
9475     case XPR_BLOCK:
9476     case XPR_STMT:
9477     case XPR_STMTLIST:
9478     case XPR_FACCESS:
9479     case XPR_ARROW:
9480     case XPR_NODE:
9481     case XPR_NUMLIT:
9482     case XPR_STRINGLITERAL:
9483       ret = cstring_undefined;
9484       break;
9485     }
9486
9487   return ret;
9488 }
9489
9490 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9491 {
9492   cstring ret;
9493   exprData data;
9494
9495   if (exprNode_isError (e))
9496     {
9497       static /*@only@*/ cstring error = cstring_undefined;
9498
9499       if (!cstring_isDefined (error))
9500         {
9501           error = cstring_makeLiteral ("<error>");
9502         }
9503       
9504       return error;
9505     }
9506
9507   data = e->edata;
9508
9509   switch (e->kind)
9510     {
9511     case XPR_PARENS: 
9512       ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9513       break;
9514     case XPR_ASSIGN:
9515       ret = message ("%s %s %s",
9516                      exprNode_unparse (exprData_getOpA (data)), 
9517                      lltok_unparse (exprData_getOpTok (data)),
9518                      exprNode_unparse (exprData_getOpB (data)));
9519       break;
9520     case XPR_CALL:
9521       ret = message ("%s(%q)",
9522                      exprNode_unparse (exprData_getFcn (data)), 
9523                      exprNodeList_unparse (exprData_getArgs (data)));
9524       break;
9525     case XPR_INITBLOCK:
9526       ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9527       break;
9528     case XPR_EMPTY:
9529       ret = cstring_undefined;
9530       break;
9531     case XPR_LABEL:
9532       ret = message ("%s:", exprData_getId (data));
9533       break;
9534     case XPR_CONST:
9535     case XPR_VAR:
9536       ret = cstring_copy (exprData_getId (data));
9537       break;
9538     case XPR_FETCH:
9539       ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9540                      exprNode_unparse (exprData_getPairB (data)));
9541       break;
9542     case XPR_BODY:
9543       ret = message ("<body>");
9544       break;
9545     case XPR_OP:
9546       ret = message ("%s %s %s",
9547                      exprNode_unparse (exprData_getOpA (data)), 
9548                      lltok_unparse (exprData_getOpTok (data)),
9549                      exprNode_unparse (exprData_getOpB (data))); 
9550       break;
9551       
9552     case XPR_PREOP: 
9553       ret = message ("%s%s",
9554                      lltok_unparse (exprData_getUopTok (data)),
9555                      exprNode_unparse (exprData_getUopNode (data))); 
9556       break;
9557
9558     case XPR_POSTOP:
9559       ret = message ("%s%s",
9560                      exprNode_unparse (exprData_getUopNode (data)),
9561                      lltok_unparse (exprData_getUopTok (data))); 
9562       break;
9563       
9564     case XPR_OFFSETOF:
9565       ret = message ("offsetof(%s,%q)", 
9566                      ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9567                      cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9568       break;
9569
9570     case XPR_SIZEOFT:
9571       ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9572       break;
9573       
9574     case XPR_SIZEOF:
9575       ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9576       break;
9577
9578     case XPR_ALIGNOFT:
9579       ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9580       break;
9581       
9582     case XPR_ALIGNOF:
9583       ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9584       break;
9585       
9586     case XPR_VAARG:
9587       ret = message ("va_arg(%s, %q)", 
9588                      exprNode_unparse (exprData_getCastNode (data)),
9589                      qtype_unparse (exprData_getCastType (data)));
9590       break;
9591       
9592     case XPR_ITERCALL:
9593       ret = message ("%q(%q)", 
9594                      uentry_getName (exprData_getIterCallIter (data)),
9595                      exprNodeList_unparse (exprData_getIterCallArgs (data)));
9596       break;
9597     case XPR_ITER:
9598       ret = message ("%q(%q) %s %q",
9599                      uentry_getName (exprData_getIterSname (data)),
9600                      exprNodeList_unparse (exprData_getIterAlist (data)),
9601                      exprNode_unparse (exprData_getIterBody (data)),
9602                      uentry_getName (exprData_getIterEname (data)));
9603       break;
9604     case XPR_CAST:
9605       ret = message ("(%q)%s", 
9606                      qtype_unparse (exprData_getCastType (data)),
9607                      exprNode_unparse (exprData_getCastNode (data)));
9608       break;
9609       
9610     case XPR_FOR:
9611       ret = message ("%s %s", 
9612                      exprNode_unparse (exprData_getPairA (data)), 
9613                      exprNode_unparse (exprData_getPairB (data)));
9614       break;
9615
9616     case XPR_FORPRED:
9617             ret = message ("for (%s; %s; %s)",
9618                      exprNode_unparse (exprData_getTripleInit (data)),
9619                      exprNode_unparse (exprData_getTripleTest (data)),
9620                      exprNode_unparse (exprData_getTripleInc (data)));
9621       break;
9622       
9623     case XPR_GOTO:
9624       ret = message ("goto %s", exprData_getLiteral (data));
9625       break;
9626
9627     case XPR_CONTINUE:
9628       ret = cstring_makeLiteral ("continue");
9629       break;
9630
9631     case XPR_BREAK:
9632       ret = cstring_makeLiteral ("break");
9633       break;
9634
9635     case XPR_RETURN:
9636       ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9637       break;
9638
9639     case XPR_NULLRETURN:
9640       ret = cstring_makeLiteral ("return");
9641       break;
9642
9643     case XPR_COMMA:
9644       ret = message ("%s, %s", 
9645                      exprNode_unparse (exprData_getPairA (data)),
9646                      exprNode_unparse (exprData_getPairB (data)));
9647       break;
9648       
9649     case XPR_COND:
9650       ret = message ("%s ? %s : %s",
9651                      exprNode_unparse (exprData_getTriplePred (data)),
9652                      exprNode_unparse (exprData_getTripleTrue (data)),
9653                      exprNode_unparse (exprData_getTripleFalse (data)));
9654       break;
9655     case XPR_IF:
9656       ret = message ("if (%s) %s", 
9657                      exprNode_unparse (exprData_getPairA (data)),
9658                      exprNode_unparse (exprData_getPairB (data)));
9659       break;
9660       
9661     case XPR_IFELSE:
9662       ret = message ("if (%s) %s else %s",
9663                      exprNode_unparse (exprData_getTriplePred (data)),
9664                      exprNode_unparse (exprData_getTripleTrue (data)),
9665                      exprNode_unparse (exprData_getTripleFalse (data)));
9666       break;
9667     case XPR_WHILE:
9668       ret = message ("while (%s) %s",
9669                      exprNode_unparse (exprData_getPairA (data)),
9670                      exprNode_unparse (exprData_getPairB (data)));
9671       break;
9672
9673     case XPR_WHILEPRED:
9674       ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9675       break;
9676
9677     case XPR_TOK:
9678       ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9679       break;
9680
9681     case XPR_DOWHILE:
9682       ret = message ("do { %s } while (%s)",
9683                      exprNode_unparse (exprData_getPairB (data)),
9684                      exprNode_unparse (exprData_getPairA (data)));
9685       break;
9686       
9687     case XPR_BLOCK:
9688       ret = message ("{ %s }", exprNode_unparse (exprData_getSingle (data)));
9689       /* evans 2002-02-20 was unparseFirst! */
9690       break;
9691
9692     case XPR_STMT:
9693       ret = message ("%s;", exprNode_unparse (exprData_getUopNode (data)));
9694       break;
9695
9696     case XPR_STMTLIST:
9697       if (exprNode_isStatement (exprData_getPairA (data)))
9698         {
9699           /*
9700           ** statement expressions already print the ;
9701           */
9702
9703           ret = message ("%s %s", 
9704                          exprNode_unparse (exprData_getPairA (data)),
9705                          exprNode_unparse (exprData_getPairB (data)));
9706         }
9707       else
9708         {
9709           ret = message ("%s; %s", 
9710                          exprNode_unparse (exprData_getPairA (data)),
9711                          exprNode_unparse (exprData_getPairB (data)));
9712         }
9713       break;
9714       
9715     case XPR_FTDEFAULT:
9716     case XPR_DEFAULT:
9717       ret = cstring_makeLiteral ("default:");
9718       break;
9719
9720     case XPR_SWITCH:
9721       ret = message ("switch (%s) %s", 
9722                      exprNode_unparse (exprData_getPairA (data)),
9723                      exprNode_unparse (exprData_getPairB (data)));
9724       break;
9725
9726     case XPR_FTCASE:
9727     case XPR_CASE:
9728       ret = message ("case %s:", 
9729                      exprNode_unparse (exprData_getSingle (data)));
9730       break;
9731       
9732     case XPR_INIT:
9733       if (exprNode_isError (exprData_getInitNode (data)))
9734         {
9735           ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9736         }
9737       else
9738         {
9739           ret = message ("%q = %s",
9740                          idDecl_unparseC (exprData_getInitId (data)),
9741                          exprNode_unparse (exprData_getInitNode (data)));
9742         }
9743       break;
9744       
9745     case XPR_FACCESS:
9746       ret = message ("%s.%s",
9747                      exprNode_unparse (exprData_getFieldNode (data)),
9748                      exprData_getFieldName (data));
9749       break;
9750       
9751     case XPR_ARROW:
9752             ret = message ("%s->%s",
9753                      exprNode_unparse (exprData_getFieldNode (data)),
9754                      exprData_getFieldName (data));
9755       break;
9756
9757     case XPR_STRINGLITERAL:
9758       if (ctype_isWideString (e->typ))
9759         {
9760           ret = message ("L\"%s\"", exprData_getLiteral (data));
9761         }
9762       else
9763         {
9764           ret = message ("\"%s\"", exprData_getLiteral (data));
9765         }
9766       break;
9767
9768     case XPR_NUMLIT:
9769       ret = cstring_copy (exprData_getLiteral (data));
9770       break;
9771
9772     case XPR_NODE:
9773       ret = cstring_makeLiteral ("<node>");
9774       break;
9775     }
9776
9777   return ret;
9778 }
9779
9780 bool
9781 exprNode_isInitializer (exprNode e)
9782 {
9783   return (exprNode_isDefined (e)
9784           && e->kind == XPR_INIT);
9785 }
9786
9787 bool 
9788 exprNode_isCharLiteral (exprNode e)
9789 {
9790   if (exprNode_isDefined (e))
9791     {
9792       return (multiVal_isChar (exprNode_getValue (e)));
9793     }
9794   else
9795     {
9796       return FALSE;
9797     }
9798 }
9799
9800 bool
9801 exprNode_isNumLiteral (exprNode e)
9802 {
9803   if (exprNode_isDefined (e))
9804     {
9805       return (multiVal_isInt (exprNode_getValue (e)));
9806     }
9807   else
9808     {
9809       return FALSE;
9810     }
9811 }
9812
9813 static bool
9814 exprNode_isFalseConstant (exprNode e)
9815 {
9816   if (exprNode_isDefined (e))
9817     {
9818       cstring s = exprNode_rootVarName (e);
9819
9820       if (cstring_equal (s, context_getFalseName ()))
9821         {
9822           return TRUE;
9823         }
9824     }
9825
9826   return FALSE;
9827 }
9828
9829 bool
9830 exprNode_matchLiteral (ctype expected, exprNode e)
9831 {
9832   if (exprNode_isDefined (e))
9833     {
9834       multiVal m = exprNode_getValue (e);
9835       
9836       if (multiVal_isDefined (m))
9837         {
9838           if (multiVal_isInt (m))
9839             {
9840               long int val = multiVal_forceInt (m);
9841               
9842               if (ctype_isNumAbstract (expected)  
9843                   && context_flagOn (FLG_NUMABSTRACTLIT, exprNode_loc (e))) 
9844                 {
9845                   return TRUE;
9846                 }
9847
9848               if (ctype_isDirectBool (ctype_realishType (expected)))
9849                 {
9850                   if (val == 0) 
9851                     {
9852                       return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9853                     }
9854                   else 
9855                     {
9856                       return FALSE;
9857                     }
9858                 }
9859               
9860               if (ctype_isRealInt (expected))
9861                 {
9862                   /*
9863                   ** unsigned <- [ constant >= 0 is okay ]
9864                   */
9865                   
9866                   if (ctype_isUnsigned (expected))
9867                     {
9868                       if (val < 0)
9869                         {
9870                           return FALSE;
9871                         }
9872                     }
9873                   
9874                   /*
9875                   ** No checks on sizes of integers...maybe add
9876                   ** these later.
9877                   */
9878
9879                   DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9880                   DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9881                             bool_unparse (ctype_isInt (exprNode_getType (e)))));
9882
9883                   if (context_getFlag (FLG_NUMLITERAL) 
9884                       && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9885                     return TRUE;
9886                   } else {
9887                     if (val == 0) {
9888                       return TRUE;
9889                     } else {
9890                       return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9891                     }
9892                   }
9893                 }
9894               else if (ctype_isChar (expected))
9895                 {
9896                   return FALSE;
9897                 }
9898               else if (ctype_isArrayPtr (expected))
9899                 {
9900                   /* 
9901                   ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9902                   */
9903
9904                   if (val == 0)
9905                     {
9906                       if (ctype_match (exprNode_getType (e), expected)
9907                           || ctype_isVoidPointer (exprNode_getType (e)))
9908                         {
9909                           return TRUE;
9910                         }
9911                     }
9912                   else
9913                     {
9914                       return FALSE;
9915                     }
9916                 }
9917               else if (ctype_isAnyFloat (expected))
9918                 {
9919                   return (context_getFlag (FLG_NUMLITERAL));
9920                 }
9921               else
9922                 {
9923                   return FALSE;
9924                 }
9925             }
9926           else if (multiVal_isDouble (m))
9927             {
9928               if (ctype_isAnyFloat (expected))
9929                 {
9930                   return TRUE;
9931                 }
9932             }
9933           else if (multiVal_isChar (m))
9934             {
9935               /*signed? */ char val = multiVal_forceChar (m);      
9936               
9937               if (ctype_isChar (expected))
9938                 {
9939                   if (ctype_isUnsigned (expected) && ((int) val) < 0)
9940                     {
9941                       return FALSE;
9942                     }
9943                   else
9944                     {
9945                       return TRUE;
9946                     }
9947                 }
9948             }
9949           else
9950             {
9951               return FALSE;
9952             }
9953         }
9954     }
9955   
9956   return FALSE;
9957 }
9958
9959 bool
9960 exprNode_matchType (ctype expected, exprNode e)
9961 {
9962   ctype actual;
9963   
9964   if (!exprNode_isDefined (e)) return TRUE;
9965
9966   actual = ctype_realishType (exprNode_getType (e));
9967
9968   if (ctype_match (ctype_realishType (expected), actual))
9969     {
9970       return TRUE;
9971     }
9972
9973   llassert (!exprNode_isError (e));
9974   return (exprNode_matchLiteral (expected, e));
9975 }
9976
9977 static bool
9978 exprNode_matchTypes (exprNode e1, exprNode e2)
9979 {
9980   ctype t1;
9981   ctype t2;
9982  
9983   if (!exprNode_isDefined (e1)) return TRUE;
9984   if (!exprNode_isDefined (e2)) return TRUE;
9985
9986   /*
9987   ** realish type --- keep bools, bools 
9988   */ 
9989
9990   t1 = ctype_realishType (exprNode_getType (e1));
9991   t2 = ctype_realishType (exprNode_getType (e2));
9992
9993   if (ctype_match (t1, t2)) 
9994     {
9995       return TRUE;
9996     }
9997
9998   DPRINTF (("Matching literal! %s %s %s %s",
9999             ctype_unparse (t1), exprNode_unparse (e2),
10000             ctype_unparse (t2), exprNode_unparse (e1)));
10001
10002   return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
10003 }
10004
10005 /*
10006 ** pass e as ct
10007 */
10008
10009 static bool
10010   exprNode_matchArgType (ctype ct, exprNode e)
10011 {
10012   ctype et;
10013
10014   if (!exprNode_isDefined (e))
10015     {
10016       return TRUE;
10017     }
10018
10019   et = ctype_realType (exprNode_getType (e));
10020
10021   if (ctype_matchArg (ct, et)) return TRUE;
10022   
10023   llassert (!exprNode_isError (e));
10024   return (exprNode_matchLiteral (ct, e));
10025 }
10026
10027 static /*@only@*/ exprNodeSList
10028   exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
10029 {
10030   if (exprNode_isDefined (e))
10031     {
10032       if (e->kind == XPR_STMTLIST)
10033         {
10034           return (exprNodeSList_append
10035                   (exprNode_flatten (exprData_getPairA (e->edata)),
10036                    exprNode_flatten (exprData_getPairB (e->edata))));
10037         }
10038       else if (e->kind == XPR_BLOCK)
10039         {
10040           return (exprNode_flatten (exprData_getSingle (e->edata)));
10041         }
10042       else
10043         {
10044           return (exprNodeSList_singleton (e));
10045         }
10046     }
10047
10048   return exprNodeSList_new ();
10049 }
10050
10051 static /*@exposed@*/ exprNode
10052 exprNode_lastStatement (/*@returned@*/ exprNode e)
10053 {
10054   if (exprNode_isDefined (e))
10055     {
10056       if (e->kind == XPR_STMTLIST)
10057         {
10058           exprNode b = exprData_getPairB (e->edata);
10059
10060           if (exprNode_isDefined (b))
10061             {
10062               return exprNode_lastStatement (b);
10063             }
10064           else
10065             {
10066               return exprNode_lastStatement (exprData_getPairA (e->edata));
10067             }
10068         }
10069       else if (e->kind == XPR_BLOCK)
10070         {
10071           return (exprNode_lastStatement (exprData_getSingle (e->edata)));
10072         }
10073       else
10074         {
10075           return (e);
10076         }
10077     }
10078
10079   return exprNode_undefined;
10080 }
10081
10082 static /*@exposed@*/ exprNode
10083 exprNode_firstStatement (/*@returned@*/ exprNode e)
10084 {
10085   if (exprNode_isDefined (e))
10086     {
10087       if (e->kind == XPR_STMTLIST)
10088         {
10089           exprNode b = exprData_getPairA (e->edata);
10090
10091           if (exprNode_isDefined (b))
10092             {
10093               return exprNode_firstStatement (b);
10094             }
10095           else
10096             {
10097               return exprNode_firstStatement (exprData_getPairB (e->edata));
10098             }
10099         }
10100       else if (e->kind == XPR_BLOCK)
10101         {
10102           return (exprNode_firstStatement (exprData_getSingle (e->edata)));
10103         }
10104       else
10105         {
10106           return (e);
10107         }
10108     }
10109
10110   return exprNode_undefined;
10111 }
10112   
10113 static void
10114 exprNode_mergeUSs (exprNode res, exprNode other)
10115 {
10116   if (exprNode_isDefined (res) && exprNode_isDefined (other))
10117     {
10118       res->msets = sRefSet_union (res->msets, other->msets);
10119       res->sets = sRefSet_union (res->sets, other->sets);
10120       res->uses = sRefSet_union (res->uses, other->uses);
10121     }
10122 }
10123
10124 static void
10125 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
10126 {
10127   if (exprNode_isDefined (res))
10128     {
10129       if (exprNode_isDefined (other1))
10130         {
10131           res->sets = sRefSet_union (res->sets, other1->sets);
10132           res->msets = sRefSet_union (res->msets, other1->msets);
10133           res->uses = sRefSet_union (res->uses, other1->uses);
10134         }
10135       if (exprNode_isDefined (other2))
10136         {
10137           res->sets = sRefSet_union (res->sets, other2->sets);
10138           res->msets = sRefSet_union (res->msets, other2->msets);
10139           res->uses = sRefSet_union (res->uses, other2->uses);
10140         }
10141     }
10142 }
10143
10144 /*
10145 ** modifies e->uses
10146 **
10147 ** Reports errors is s is not defined.
10148 */
10149
10150 static void
10151 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
10152 {
10153   if (exprNode_isDefined (e))
10154     {
10155       e->uses = sRefSet_insert (e->uses, s);
10156     }
10157 }
10158   
10159 void
10160 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
10161 {
10162   if (sRef_isKnown (s) && !sRef_isConst (s))
10163     {
10164       /*
10165       ** need to check all outer types are useable
10166       */
10167
10168       DPRINTF (("Check use: %s / %s",
10169                 exprNode_unparse (e), sRef_unparse (s)));
10170       
10171       exprNode_addUse (e, s);
10172      
10173       if (!context_inProtectVars ())
10174         {
10175           /*
10176           ** only report the deepest error
10177           */
10178           
10179           sRef errorRef = sRef_undefined;
10180           sRef lastRef  = sRef_undefined;
10181           bool deadRef = FALSE;
10182           bool unuseable = FALSE;
10183           bool errorMaybe = FALSE;
10184           
10185           while (sRef_isValid (s) && sRef_isKnown (s))
10186             {
10187               ynm readable = sRef_isValidLvalue (s);
10188
10189               DPRINTF (("Readable: %s / %s",
10190                         sRef_unparseFull (s), ynm_unparse (readable)));
10191
10192               if (!(ynm_toBoolStrict (readable)))
10193                 {
10194                   if (ynm_isMaybe (readable))
10195                     {
10196                       lastRef = errorRef;
10197                       errorRef = s;
10198                       DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10199                       deadRef = sRef_isPossiblyDead (errorRef);
10200                       unuseable = sRef_isUnuseable (errorRef);
10201                       errorMaybe = TRUE;
10202                     }
10203                   else
10204                     {
10205                       lastRef = errorRef;
10206                       errorRef = s;
10207                       DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10208                       deadRef = sRef_isDead (errorRef);
10209                       unuseable = sRef_isUnuseable (errorRef);
10210                       errorMaybe = FALSE;
10211                     }
10212
10213                   /*
10214                   if (!sRef_isPartial (s))
10215                     {
10216                       DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10217                       sRef_setDefined (s, loc);
10218                       DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10219                     }
10220                   */
10221                 }
10222
10223               s = sRef_getBaseSafe (s);
10224             } /* end while */
10225           
10226           if (sRef_isValid (errorRef)) 
10227             {
10228               if (sRef_isValid (lastRef) && sRef_isField (lastRef) 
10229                   && sRef_isPointer (errorRef))
10230                 {
10231                   errorRef = lastRef;
10232                   DPRINTF (("errorRef: %s", sRef_unparseFull (errorRef)));
10233                 }
10234               
10235               if (deadRef)
10236                 {
10237                   if (sRef_isThroughArrayFetch (errorRef))
10238                     {
10239                       if (optgenerror 
10240                           (FLG_STRICTUSERELEASED,
10241                            message ("%q %q may be used after being released", 
10242                                     sRef_unparseKindNamePlain (errorRef),
10243                                     sRef_unparse (errorRef)),
10244                            loc))
10245                         {
10246                           sRef_showRefKilled (errorRef);
10247                           
10248                           if (sRef_isKept (errorRef))
10249                             {
10250                               sRef_clearAliasState (errorRef, loc);
10251                             }
10252                         }
10253                     }
10254                   else
10255                     {
10256                       DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10257
10258                       if (optgenerror
10259                           (FLG_USERELEASED,
10260                            message ("%q %q %qused after being released", 
10261                                     sRef_unparseKindNamePlain (errorRef),
10262                                     sRef_unparse (errorRef),
10263                                     cstring_makeLiteral (errorMaybe 
10264                                                          ? "may be " : "")),
10265                            loc))
10266                         {
10267                           sRef_showRefKilled (errorRef);
10268                           
10269                           if (sRef_isKept (errorRef))
10270                             {
10271                               sRef_clearAliasState (errorRef, loc);
10272                             }
10273                         }
10274                     }
10275                 }
10276               else if (unuseable)
10277                 {
10278                   if (optgenerror
10279                       (FLG_USEDEF,
10280                        message ("%q %q%qused in inconsistent state", 
10281                                 sRef_unparseKindName (errorRef),
10282                                 sRef_unparseOpt (errorRef),
10283                                 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10284                        loc))
10285                     {
10286                       sRef_showStateInconsistent (errorRef);
10287                     }
10288                 }
10289               else
10290                 {
10291                   DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10292
10293                   if (optgenerror 
10294                       (FLG_USEDEF,
10295                        message ("%q %q%qused before definition", 
10296                                 sRef_unparseKindName (errorRef),
10297                                 sRef_unparseOpt (errorRef),
10298                                 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10299                        loc))
10300                     {
10301                       ;
10302                     }
10303
10304                   DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10305                 }
10306               
10307               sRef_setDefined (errorRef, loc);
10308           
10309               if (sRef_isAddress (errorRef))
10310                 {
10311                   sRef_setDefined (sRef_getRootBase (errorRef), loc);
10312                 }
10313             } /* end is error */
10314         }
10315     }
10316
10317   setCodePoint ();
10318 }
10319
10320 static void
10321 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10322 {
10323   if (exprNode_isDefined (e) && sRef_isKnown (s))
10324     {
10325       e->uses = sRefSet_insert (e->uses, s);
10326     }
10327 }
10328
10329 static void
10330 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10331 {
10332   if (exprNode_isDefined (e))
10333     {
10334       e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10335     }
10336 }
10337
10338 void
10339 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10340 {
10341   sRef defines = sRef_undefined;
10342
10343   if (sRef_isValid (s) && !sRef_isNothing (s))
10344     {
10345       uentry ue = sRef_getBaseUentry (s);
10346
10347       if (uentry_isValid (ue))
10348         {
10349           uentry_setLset (ue);
10350         }
10351
10352       if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10353         {
10354           voptgenerror (FLG_USEDEF,
10355                         message ("Attempt to set unuseable storage: %q", 
10356                                  sRef_unparse (s)),
10357                         exprNode_loc (e));
10358         }
10359      
10360       if (sRef_isMeaningful (s))
10361         {         
10362           if (sRef_isDead (s))
10363             {
10364               sRef base = sRef_getBaseSafe (s);
10365
10366               if (sRef_isValid (base) 
10367                   && sRef_isDead (base))
10368                 {
10369                   sRef_setPartial (s, exprNode_loc (e));
10370                 }
10371               
10372               defines = s; /* okay - modifies for only param */
10373             }
10374           else if (sRef_isPartial (s))
10375             {
10376               sRef eref = exprNode_getSref (e);
10377
10378               if (!sRef_isPartial (eref))
10379                 {
10380                   /*
10381                   ** should do something different here???
10382                   */
10383                   
10384                   sRef_setDefinedComplete (eref, exprNode_loc (e));               
10385                 }
10386               else
10387                 {
10388                   sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10389                 }
10390
10391               if (sRef_isMeaningful (eref))
10392                 {
10393                   defines = eref;
10394                 }
10395               else
10396                 {                
10397                   defines = s;
10398                 }
10399             }
10400           else if (sRef_isAllocated (s))
10401             {
10402               sRef eref = exprNode_getSref (e);
10403
10404               
10405               if (!sRef_isAllocated (eref))
10406                 {
10407                   sRef_setDefinedComplete (eref, exprNode_loc (e));
10408                 }
10409               else
10410                 {
10411                   sRef base = sRef_getBaseSafe (eref);
10412                   
10413                   if (sRef_isValid (base))
10414                     {
10415                       sRef_setPdefined (base, exprNode_loc (e)); 
10416                     }
10417                 }
10418
10419               defines = s;
10420             }
10421           else 
10422             {
10423               sRef_setDefinedNCComplete (s, exprNode_loc (e));
10424               defines = s;
10425             }
10426
10427         }
10428       else /* not meaningful...but still need to insert it */
10429         {
10430           defines = s;
10431         }
10432     }
10433
10434   if (exprNode_isDefined (e) && sRef_isValid (defines))
10435     {
10436       e->sets = sRefSet_insert (e->sets, defines); 
10437     }
10438 }
10439
10440 void
10441 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10442 {
10443   if (sRef_isValid (s) && !sRef_isNothing (s))
10444     {
10445       uentry ue = sRef_getBaseUentry (s);
10446
10447       if (uentry_isValid (ue))
10448         {
10449           uentry_setLset (ue);
10450         }
10451
10452       if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10453         {
10454           voptgenerror (FLG_USEDEF,
10455                         message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10456                         exprNode_loc (e));
10457         }
10458       
10459       if (sRef_isMeaningful (s))
10460         {
10461           sRef_setDefinedComplete (s, exprNode_loc (e));
10462         }
10463       
10464       if (exprNode_isDefined (e))
10465         {
10466           e->msets = sRefSet_insert (e->msets, s);
10467         }
10468     }
10469 }
10470
10471 static void
10472 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10473 {
10474   checkAnyCall (fcn, cstring_undefined, params, args, 
10475                 FALSE, sRefSet_undefined, FALSE, 0);
10476 }
10477
10478 static void
10479 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current, 
10480              /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10481 {
10482   setCodePoint ();
10483   
10484   if (uentry_isYield (ucurrent))
10485     {
10486       sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10487       exprNode_checkSet (current, current->sref);
10488     }
10489   else 
10490     {
10491       if (uentry_isSefParam (ucurrent))
10492         {
10493           sRefSet sets = current->sets;
10494           sRef ref = exprNode_getSref (current);
10495
10496           if (sRef_isMacroParamRef (ref))
10497             {
10498               uentry ue = sRef_getUentry (ref);
10499
10500               if (!uentry_isSefParam (ue))
10501                 {
10502                   voptgenerror 
10503                     (FLG_SEFPARAMS,
10504                      message
10505                      ("Parameter %d to %s is declared sef, but "
10506                       "the argument is a macro parameter declared "
10507                       "without sef: %s",
10508                       argno, exprNode_unparse (fcn),
10509                       exprNode_unparse (current)),
10510                      exprNode_loc (current));
10511                 }
10512             }
10513
10514           if (!sRefSet_isEmpty (sets))
10515             {
10516               sRefSet reported = sRefSet_undefined;
10517               
10518               sRefSet_realElements (current->sets, el)
10519                 {
10520                   if (sRefSet_isSameNameMember (reported, el))
10521                     {
10522                       ; /* don't report again */
10523                     }
10524                   else
10525                     {
10526                       if (sRef_isUnconstrained (el))
10527                         {
10528                           voptgenerror 
10529                             (FLG_SEFUNSPEC,
10530                              message
10531                              ("Parameter %d to %s is declared sef, but "
10532                               "the argument calls unconstrained function %s "
10533                               "(no guarantee it will not modify something): %s",
10534                               argno, exprNode_unparse (fcn),
10535                               sRef_unconstrainedName (el),
10536                               exprNode_unparse (current)),
10537                              exprNode_loc (current));
10538                         }
10539                       else
10540                         {
10541                           voptgenerror 
10542                             (FLG_SEFPARAMS,
10543                              message
10544                              ("Parameter %d to %s is declared sef, but "
10545                               "the argument may modify %q: %s",
10546                               argno, exprNode_unparse (fcn),
10547                               sRef_unparse (el),
10548                               exprNode_unparse (current)),
10549                              exprNode_loc (current));
10550                         }
10551                     } 
10552                 } end_sRefSet_realElements;
10553             }
10554         }
10555       
10556       transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10557       exprNode_mergeUSs (fcn, current);
10558     }
10559 }
10560
10561 static void
10562   checkAnyCall (/*@dependent@*/ exprNode fcn, 
10563                 /*@dependent@*/ cstring fname,
10564                 uentryList pn, 
10565                 exprNodeList args, 
10566                 bool hasMods, sRefSet mods,
10567                 bool isSpec,
10568                 int specialArgs)
10569 {
10570   int paramno = 0;
10571   int nargs = exprNodeList_size (args);
10572
10573   setCodePoint ();
10574
10575   /*
10576   ** concat all args ud's to f, add each arg sref as a use unless
10577   ** it was specified as "out", in which case it is a def.
10578   */
10579   
10580   uentryList_reset (pn);
10581   
10582   /*
10583   ** aliasing checks:
10584   **
10585   **    if paramn is only or unique, no other arg may alias argn
10586   */
10587   
10588   exprNodeList_elements (args, current) 
10589     {
10590       paramno++;
10591       
10592       if (exprNode_isDefined (current)) 
10593         {
10594           if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn))) 
10595             {
10596               uentry ucurrent = uentryList_current (pn);
10597               
10598               if (specialArgs == 0 
10599                   || (paramno < specialArgs))
10600                 {
10601                   checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10602
10603                   if (context_maybeSet (FLG_ALIASUNIQUE))
10604                     {
10605                       if (uentry_isOnly (ucurrent)
10606                           || uentry_isUnique (ucurrent))
10607                         {
10608                           checkUniqueParams (fcn, current, args,
10609                                              paramno, ucurrent);
10610                         }
10611                     }
10612                 } 
10613             }
10614           else /* uentry is undefined */
10615             {
10616               if (specialArgs == 0)
10617                 {
10618                   exprNode_checkUseParam (current);
10619                 }
10620
10621               exprNode_mergeUSs (fcn, current);
10622             }   
10623         }
10624       uentryList_advanceSafe (pn);
10625     } end_exprNodeList_elements;
10626   
10627   if (hasMods)
10628     {
10629       setCodePoint ();
10630
10631       sRefSet_allElements (mods, s)
10632         {
10633           sRef fb;
10634           sRef rb = sRef_getRootBase (s);
10635           
10636           if (sRef_isFileOrGlobalScope (rb))
10637             {
10638               context_usedGlobal (rb);
10639             }
10640           
10641           fb = sRef_fixBaseParam (s, args);
10642           
10643           if (!sRef_isMacroParamRef (fb))
10644             {
10645               if (sRef_isNothing (fb))
10646                 {
10647                   ;
10648                 }
10649               else
10650                 {
10651                   if (sRef_isValid (fb))
10652                     {
10653                       uentry ue = sRef_getBaseUentry (s);
10654                       
10655                       if (uentry_isValid (ue))
10656                         {
10657                           uentry_setLset (ue);
10658                         }
10659                     }
10660                   
10661                   fcn->sets = sRefSet_insert (fcn->sets, fb);
10662                 }
10663             }
10664           sRef_clearDerivedComplete (s); 
10665         } end_sRefSet_allElements;
10666       
10667       setCodePoint ();
10668     }
10669   else
10670     {
10671       if (context_hasMods ())
10672         {
10673           if (context_maybeSet (FLG_MODUNCON))
10674             {
10675               voptgenerror
10676                 (FLG_MODUNCON,
10677                  message ("Undetected modification possible "
10678                           "from call to unconstrained function %s: %s", 
10679                           fname,
10680                           exprNode_unparse (fcn)),
10681                  exprNode_loc (fcn));
10682             }
10683         }
10684       else
10685         {
10686           if (context_maybeSet (FLG_MODUNCONNOMODS)
10687               && !(context_inIterDef () || context_inIterEnd ()))
10688             {
10689               voptgenerror
10690                 (FLG_MODUNCONNOMODS,
10691                  message ("Undetected modification possible "
10692                           "from call to unconstrained function %s: %s", 
10693                           fname,
10694                           exprNode_unparse (fcn)),
10695                  exprNode_loc (fcn));
10696             }
10697         }
10698
10699       exprNode_checkSetAny (fcn, fname);
10700     }
10701 }
10702
10703 void exprNode_checkUseParam (exprNode current)
10704 {
10705   if (exprNode_isDefined (current))
10706     {
10707       exprNode_checkUse (current, current->sref, current->loc);
10708     }
10709 }
10710
10711 static ctype
10712   checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10713                  /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10714                  lltok op)
10715 {
10716   ctype ret = tr1;
10717   
10718   if (!ctype_match (tr1, tr2))
10719     {
10720       if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10721           (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10722         {
10723           DPRINTF (("No error: [%s] %s / [%s]  %s",
10724                     exprNode_unparse (e1), ctype_unparse (tr1),
10725                     exprNode_unparse (e2), ctype_unparse (tr2)));
10726           
10727           /*
10728           ** evans 2003-06-15: changed this so if either type is a literal,
10729           **    the other type is used.
10730           **    (Need to look at the ISO C99 rules on this...)
10731           */
10732
10733           if (exprNode_isNumLiteral (e1)) {
10734             ret = tr2;
10735           } else if (exprNode_isNumLiteral (e2)) {
10736             ret = tr1;
10737           } else {
10738             ret = ctype_biggerType (tr1, tr2);
10739           }
10740         }
10741       else
10742         {
10743           if (ctype_isNumAbstract (tr1) 
10744               && exprNode_isNumLiteral (e2)
10745               && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10746             {
10747               ret = tr1; /* No error */
10748             }
10749           else if (ctype_isNumAbstract (tr2)
10750                    && exprNode_isNumLiteral (e1)
10751                    && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10752             {
10753               ret = tr2;
10754             }
10755           else 
10756             {
10757               if (gentypeerror 
10758                   (tr1, e1, tr2, e2,
10759                    message ("Incompatible types for %s (%s, %s): %s %s %s",
10760                             lltok_unparse (op),
10761                             ctype_unparse (te1),
10762                             ctype_unparse (te2),
10763                             exprNode_unparse (e1), lltok_unparse (op), 
10764                             exprNode_unparse (e2)),
10765                    e1->loc))
10766                 {
10767                   ret = ctype_unknown;
10768                 }
10769               else 
10770                 {
10771                   ret = ctype_biggerType (tr1, tr2);
10772                 }
10773             }
10774         }
10775     }
10776   else
10777     {
10778       if (ctype_isNumAbstract (tr1))
10779         {
10780           ret = tr1;
10781         }
10782       else if (ctype_isForceRealNumeric (&tr1)
10783                && ctype_isForceRealNumeric (&tr2))
10784         {
10785           ret = ctype_resolveNumerics (tr1, tr2);
10786         }
10787       else if (!context_msgStrictOps ()) 
10788         {
10789           if (ctype_isPointer (tr1))
10790             {
10791               if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10792                 {
10793                   ret = ctype_int;
10794                 }
10795               else if (ctype_isInt (tr2))
10796                 {
10797                   ret = te1;
10798                 }
10799               else
10800                 {
10801                   ret = ctype_unknown;
10802                 }
10803             }
10804           else if (ctype_isPointer (tr2))
10805             {
10806               if (ctype_isPointer (tr1))
10807                 {
10808                   ret = ctype_int;
10809                 }
10810               else if (ctype_isInt (tr1))
10811                 {
10812                   ret = te2;
10813                 }
10814               else
10815                 {
10816                   ret = ctype_unknown; 
10817                 }
10818             }
10819           else
10820             {
10821               ret = ctype_resolveNumerics (tr1, tr2);
10822             }
10823         }
10824       else
10825         {
10826           int opid = lltok_getTok (op);
10827           bool comparop = (opid == EQ_OP || opid == NE_OP 
10828                            || opid == TLT || opid == TGT
10829                            || opid == LE_OP || opid == GE_OP);
10830           
10831           if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10832             {
10833               if (comparop
10834                   && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10835                       || (ctype_isBool (tr1) && ctype_isBool (tr2))
10836                       || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10837                 {
10838                   ; /* no error */
10839                 }
10840               else
10841                 {
10842                   if (ctype_sameName (te1, te2))
10843                     {
10844                       voptgenerror
10845                         (FLG_STRICTOPS,
10846                          message ("Operands of %s are non-numeric (%t): %s %s %s",
10847                                   lltok_unparse (op), te1, 
10848                                   exprNode_unparse (e1), lltok_unparse (op), 
10849                                   exprNode_unparse (e2)),
10850                          e1->loc);
10851                     }
10852                   else
10853                     {
10854                       voptgenerror
10855                         (FLG_STRICTOPS,
10856                          message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10857                                   lltok_unparse (op), te1, te2, 
10858                                   exprNode_unparse (e1), lltok_unparse (op),
10859                                   exprNode_unparse (e2)),
10860                          e1->loc);
10861                     }
10862                 }
10863             }
10864           else if (!ctype_isNumeric (tr1))
10865             {
10866               voptgenerror
10867                 (FLG_STRICTOPS,
10868                  message ("Right operand of %s is non-numeric (%t): %s %s %s",
10869                           lltok_unparse (op), te1, 
10870                           exprNode_unparse (e1), lltok_unparse (op), 
10871                           exprNode_unparse (e2)),
10872                  e1->loc);
10873             }
10874           else 
10875             {
10876               if (!ctype_isNumeric (tr2))
10877                 {
10878                   voptgenerror
10879                     (FLG_STRICTOPS,
10880                      message ("Left operand of %s is non-numeric (%t): %s %s %s",
10881                               lltok_unparse (op), te2, 
10882                               exprNode_unparse (e1), lltok_unparse (op), 
10883                               exprNode_unparse (e2)),
10884                      e2->loc);
10885                 }
10886             }
10887           
10888           ret = ctype_unknown;
10889         }
10890     }
10891
10892   return ret;
10893 }
10894
10895 static bool
10896 abstractOpError (ctype tr1, ctype tr2, lltok op, 
10897                  /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, 
10898                  fileloc loc1, fileloc loc2)
10899 {
10900   if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10901     {
10902       if (ctype_match (tr1, tr2))
10903         {
10904           if (ctype_isRealNumAbstract (tr1)) 
10905             {
10906               ; /* No warning for numabstract types */
10907             } 
10908           else 
10909             {
10910               if (lltok_isEqOp (op) || lltok_isNotEqOp (op))
10911                 {
10912                   return optgenerror
10913                     (FLG_ABSTRACTCOMPARE,
10914                      message ("Object equality comparison (%s) on objects of abstract type (%t): %s %s %s",
10915                               lltok_unparse (op), tr1, 
10916                               exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10917                      loc1);
10918                 }
10919               else
10920                 {
10921                   return optgenerror
10922                     (FLG_ABSTRACT,
10923                      message ("Operands of %s are abstract type (%t): %s %s %s",
10924                               lltok_unparse (op), tr1, 
10925                               exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10926                      loc1);
10927                 }
10928             }
10929         }
10930       else
10931         {
10932           if (ctype_isRealNumAbstract (tr1) && ctype_isRealNumAbstract (tr2))  
10933             {
10934               return optgenerror 
10935                 (FLG_NUMABSTRACT,
10936                  message
10937                  ("Operands of %s are different numabstract types (%t, %t): %s %s %s",
10938                   lltok_unparse (op), tr1, tr2, 
10939                   exprNode_unparse (e1), 
10940                   lltok_unparse (op), exprNode_unparse (e2)),
10941                  loc1);
10942             }
10943           else
10944             {
10945               return optgenerror 
10946                 (FLG_ABSTRACT,
10947                  message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10948                           lltok_unparse (op), tr1, tr2, 
10949                           exprNode_unparse (e1), lltok_unparse (op), 
10950                           exprNode_unparse (e2)),
10951                  loc1);
10952             }
10953         }
10954     }
10955   else if (ctype_isRealAbstract (tr1) && !ctype_isRealNumAbstract (tr1))
10956     {
10957       return optgenerror
10958         (FLG_ABSTRACT,
10959          message ("Left operand of %s is abstract type (%t): %s %s %s",
10960                   lltok_unparse (op), tr1, 
10961                   exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10962          loc1);
10963     }
10964   else 
10965     {
10966       if (ctype_isRealAbstract (tr2) && !ctype_isRealNumAbstract (tr2))
10967         {
10968           return optgenerror
10969             (FLG_ABSTRACT,
10970              message ("Right operand of %s is abstract type (%t): %s %s %s",
10971                       lltok_unparse (op), tr2, 
10972                       exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10973              loc2);
10974         }
10975     }
10976
10977   return FALSE;
10978 }
10979
10980 /*
10981 ** e1 <= e2
10982 **
10983 ** requies e1 and e2 and not error exprNode's.
10984 **
10985 ** Checks:
10986 **
10987 **    If e1 is a component of an abstract type, and e2 is mutable and client-visible, 
10988 **    the rep of the abstract type is exposed.
10989 **
10990 ** The order is very important:
10991 **
10992 **    check rep expose (move into check transfer)
10993 **    check transfer
10994 **    setup aliases
10995 */
10996
10997 /*
10998 ** This isn't really a sensible procedure, but the indententation
10999 ** was getting too deep.
11000 */
11001
11002 static void
11003 checkOneRepExpose (sRef ysr, sRef base, 
11004                    /*@notnull@*/ exprNode e1, 
11005                    /*@notnull@*/ exprNode e2, ctype ct,
11006                    sRef s2b)
11007 {
11008   if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr) 
11009         || sRef_isOwned (ysr) 
11010         || sRef_isExposed (ysr)))
11011     {
11012       if (sRef_isAnyParam (base) && !sRef_isExposed (base)
11013           && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
11014
11015         {
11016           if (sRef_isIReference (ysr))
11017             {
11018               if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11019                 {
11020                   voptgenerror 
11021                     (FLG_ASSIGNEXPOSE,
11022                      message
11023                      ("Assignment of mutable component of parameter %q "
11024                       "to component of abstract "
11025                       "type %s exposes rep: %s = %s",
11026                       sRef_unparse (base),
11027                       ctype_unparse (ct),
11028                       exprNode_unparse (e1), exprNode_unparse (e2)),
11029                      e1->loc);
11030                 }
11031               else
11032                 {
11033                   voptgenerror 
11034                     (FLG_ASSIGNEXPOSE,
11035                      message
11036                      ("Assignment of mutable component of parameter %q "
11037                       "(through alias %q) to component of abstract "
11038                       "type %s exposes rep: %s = %s",
11039                       sRef_unparse (base),
11040                       sRef_unparse (e2->sref),
11041                       ctype_unparse (ct),
11042                       exprNode_unparse (e1), exprNode_unparse (e2)),
11043                      e1->loc);
11044                 }
11045             }
11046           else
11047             {
11048               if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11049                 {
11050                   voptgenerror 
11051                     (FLG_ASSIGNEXPOSE,
11052                      message ("Assignment of mutable parameter %q "
11053                               "to component of abstract type %s "
11054                               "exposes rep: %s = %s",
11055                               sRef_unparse (base),
11056                               ctype_unparse (ct),
11057                               exprNode_unparse (e1), 
11058                               exprNode_unparse (e2)),
11059                      e1->loc);
11060                 }
11061               else
11062                 {
11063                   voptgenerror 
11064                     (FLG_ASSIGNEXPOSE,
11065                      message ("Assignment of mutable parameter %q "
11066                               "(through alias %q) to "
11067                               "component of abstract type %s exposes "
11068                               "rep: %s = %s",
11069                               sRef_unparse (base),
11070                               sRef_unparse (e2->sref),
11071                               ctype_unparse (ct),
11072                               exprNode_unparse (e1), 
11073                               exprNode_unparse (e2)),
11074                      e1->loc);
11075                 }
11076             }
11077         }
11078       
11079       if (sRef_isFileOrGlobalScope (s2b))
11080         {
11081           if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11082             {
11083               voptgenerror 
11084                 (FLG_REPEXPOSE,
11085                  message ("Assignment of global %q "
11086                           "to component of "
11087                           "abstract type %s exposes rep: %s = %s",
11088                           sRef_unparse (base),
11089                           ctype_unparse (ct),
11090                           exprNode_unparse (e1), exprNode_unparse (e2)),
11091                  e1->loc);
11092             }
11093           else
11094             {
11095               voptgenerror 
11096                 (FLG_REPEXPOSE,
11097                  message ("Assignment of global %q (through alias %q) "
11098                           "to component of "
11099                           "abstract type %s exposes rep: %s = %s",
11100                           sRef_unparse (base),
11101                           sRef_unparse (e2->sref),
11102                           ctype_unparse (ct),
11103                           exprNode_unparse (e1), exprNode_unparse (e2)),
11104                  e1->loc);
11105             }
11106         }
11107     }
11108 }
11109
11110 static void
11111 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
11112 {
11113   DPRINTF (("Do assign: %s <- %s",
11114             exprNode_unparse (e1), exprNode_unparse (e2)));
11115   DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
11116
11117   if (ctype_isRealFunction (exprNode_getType (e1))
11118       && !ctype_isRealPointer (exprNode_getType (e1)))
11119     {
11120       voptgenerror 
11121         (FLG_TYPE,
11122          message ("Invalid left-hand side of assignment (function type %s): %s",
11123                   ctype_unparse (exprNode_getType (e1)),
11124                   exprNode_unparse (e1)),
11125          e1->loc);
11126     }
11127
11128   if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
11129     {
11130       ctype t2 = exprNode_getType (e2);
11131       sRef sr = sRef_getRootBase (e1->sref);
11132       ctype ct = sRef_getType (sr);
11133
11134       if (ctype_isAbstract (t2) 
11135           && !ctype_isNumAbstract (t2)
11136           && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
11137         {
11138           /* it is immutable, okay to reference */
11139           goto donerepexpose;
11140         }
11141
11142       if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
11143         {
11144           sRef s2b = sRef_getRootBase (e2->sref);
11145           sRef s1 = e1->sref;
11146           sRef s1b = sRef_getRootBase (s1);
11147           sRefSet aliases;
11148
11149           aliases = usymtab_canAlias (e2->sref);
11150           
11151           if (!sRef_similar (s2b, s1b) 
11152               && !sRef_isExposed (s1)
11153               && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
11154             {
11155               if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b) 
11156                   && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
11157                   && !sRef_isExposed (s2b))
11158                 {
11159                   if (sRef_isIReference (e2->sref))
11160                     {
11161                       voptgenerror 
11162                         (FLG_ASSIGNEXPOSE,
11163                          message 
11164                          ("Assignment of mutable component of parameter %q "
11165                           "to component of abstract type %s exposes rep: %s = %s",
11166                           sRef_unparse (s2b),
11167                           ctype_unparse (ct),
11168                           exprNode_unparse (e1), exprNode_unparse (e2)),
11169                          e1->loc);
11170                     }
11171                   else
11172                     {
11173                       voptgenerror 
11174                         (FLG_ASSIGNEXPOSE,
11175                          message ("Assignment of mutable parameter %q to "
11176                                   "component of abstract type %s exposes rep: %s = %s",
11177                                   sRef_unparse (s2b),
11178                                   ctype_unparse (ct),
11179                                   exprNode_unparse (e1), exprNode_unparse (e2)),
11180                          e1->loc);
11181                     }
11182                 }
11183
11184               if (sRef_isFileOrGlobalScope (s2b))
11185                 {
11186                   voptgenerror
11187                     (FLG_ASSIGNEXPOSE,
11188                      message ("Assignment of global %q to component of "
11189                               "abstract type %s exposes rep: %s = %s",
11190                               sRef_unparse (s2b),
11191                               ctype_unparse (ct),
11192                               exprNode_unparse (e1), exprNode_unparse (e2)),
11193                      e1->loc);
11194                 }
11195               
11196               sRefSet_realElements (aliases, ysr)
11197                 {
11198                   sRef base = sRef_getRootBase (ysr);
11199                   
11200                   if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
11201                       || sRef_sameName (base, s1b))
11202                     {
11203                      ; /* error already reported or same sref */
11204                     }
11205                   else
11206                     {
11207                       checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
11208                     }
11209                 } end_sRefSet_realElements;
11210             }
11211           sRefSet_free (aliases);
11212         }
11213     }
11214
11215  donerepexpose:
11216
11217   /*
11218   ** function variables don't really work...
11219   */
11220
11221   if (!ctype_isFunction (ctype_realType (e2->typ)))
11222     {
11223       if (isInit)
11224         {
11225             DPRINTF (("Check init: %s / %s",
11226                       exprNode_unparse (e1), exprNode_unparse (e2)));
11227           transferChecks_initialization (e1, e2); 
11228         }
11229       else
11230         {
11231           transferChecks_assign (e1, e2); 
11232         }
11233     }
11234   else
11235     {
11236       sRef fref = e2->sref;
11237
11238       sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
11239       sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
11240
11241             /* Need to typecheck the annotation on the parameters */
11242       
11243       if (ctype_isRealFunction (e1->typ)) {
11244         uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
11245         uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
11246
11247         if (!uentryList_isMissingParams (e1p)
11248             && !uentryList_isMissingParams (e2p)
11249             && uentryList_size (e1p) > 0) {
11250           if (uentryList_size (e1p) == uentryList_size (e2p)) {
11251             int n = 0;
11252             
11253             uentryList_elements (e1p, el1) {
11254               uentry el2;
11255
11256               el2 = uentryList_getN (e2p, n);
11257               n++;
11258               uentry_checkMatchParam (el1, el2, n, e2);
11259             } end_uentryList_elements;
11260           }
11261         }
11262       }
11263     }
11264
11265   if (exprNode_isStringLiteral (e2))
11266     {
11267       exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
11268     }
11269
11270   if (isInit && sRef_isFileOrGlobalScope (e1->sref))
11271     {
11272        ;
11273     }
11274   else
11275     {
11276       DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
11277       updateAliases (e1, e2); 
11278     }
11279 }
11280
11281 static void 
11282 checkMacroParen (exprNode e)
11283 {
11284   if (exprNode_isError (e) || e->kind == XPR_CAST)
11285     {
11286      ;
11287     }
11288   else 
11289     {
11290       if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
11291         {
11292           voptgenerror 
11293             (FLG_MACROPARENS,
11294              message ("Macro parameter used without parentheses: %s", 
11295                       exprNode_unparse (e)),
11296              e->loc);
11297         }
11298     }
11299 }
11300
11301 static void
11302 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
11303 {
11304   if (isnull)
11305     {
11306       e->guards = guardSet_addTrueGuard (e->guards, e->sref);
11307     }
11308   else
11309     {
11310       e->guards = guardSet_addFalseGuard (e->guards, e->sref);
11311     }
11312 }
11313
11314 /*
11315 ** e1 <= e2
11316 **
11317 ** if e2 is a parameter or global derived location which
11318 ** can be modified (that is, e2 is a mutable abstract type,
11319 ** or a derived pointer), then e1 can alias e2.
11320 **
11321 ** e1 can alias everything which e2 can alias.
11322 **
11323 ** Also, if e1 is guarded, remove from guard sets!
11324 */
11325
11326 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
11327 {
11328   if (!context_inProtectVars ())
11329     {
11330       /*
11331       ** depends on types of e1 and e2
11332       */
11333       
11334       sRef s1 = e1->sref;
11335       sRef s2 = e2->sref;
11336       ctype t1 = exprNode_getType (e1);
11337       
11338       /* handle pointer sRefs, record fields, arrays, etc... */
11339       
11340       if (!ctype_isRealSU (t1))
11341         {
11342           DPRINTF (("Copying real! %s", ctype_unparse (t1)));
11343           sRef_copyRealDerivedComplete (s1, s2);
11344         }
11345       else
11346         {
11347           /*
11348           ** Fields should alias
11349           */
11350
11351           DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
11352         }
11353
11354       if (ctype_isMutable (t1) && sRef_isKnown (s1))
11355         {
11356           usymtab_clearAlias (s1);
11357           usymtab_addMustAlias (s1, s2); 
11358           DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
11359         }
11360       else
11361         {
11362           DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11363         }
11364
11365       if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11366         {
11367           usymtab_unguard (s1);
11368         }
11369     }
11370 }
11371
11372 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11373 {
11374   if (exprNode_isDefined (e))
11375     {
11376       e->loc = fileloc_update (e->loc, loc);
11377     }
11378   else
11379     {
11380       e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11381     }
11382
11383   return (e);
11384 }
11385
11386 static void checkUniqueParams (exprNode fcn,
11387                                /*@notnull@*/ exprNode current, 
11388                                exprNodeList args, 
11389                                int paramno, uentry ucurrent)
11390 {
11391   int iparamno = 0;
11392   sRef thisref = exprNode_getSref (current);
11393   
11394   /*
11395   ** Check if any argument could match this argument.
11396   */
11397   
11398   exprNodeList_elements (args, icurrent) 
11399     {
11400       iparamno++;
11401       
11402       if (iparamno != paramno)
11403         {
11404           sRef sr = exprNode_getSref (icurrent);
11405           
11406           if (sRef_similarRelaxed (thisref, sr))
11407             {
11408               if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11409                 {
11410                   voptgenerror 
11411                     (FLG_ALIASUNIQUE,
11412                      message
11413                      ("Parameter %d (%s) to function %s is declared %s but "
11414                       "is aliased by parameter %d (%s)",
11415                       paramno, 
11416                       exprNode_unparse (current),
11417                       exprNode_unparse (fcn),
11418                       alkind_unparse (uentry_getAliasKind (ucurrent)),
11419                       iparamno, exprNode_unparse (icurrent)),
11420                      current->loc);
11421                 }
11422             }
11423           else
11424             {
11425               sRefSet aliases = usymtab_canAlias (sr);
11426
11427               sRefSet_allElements (aliases, asr)
11428                 {
11429                   if (ctype_isUnknown (sRef_getType (thisref)))
11430                     {
11431                       sRef_setType (thisref, uentry_getType (ucurrent));
11432                     }
11433                   
11434                   if (sRef_similarRelaxed (thisref, asr)) 
11435                     {
11436                       if (sRef_isExternal (asr))  
11437                         {
11438                           if (sRef_isLocalState (thisref))
11439                             {
11440                               ; /* okay */
11441                             }
11442                           else
11443                             {
11444                               sRef base = sRef_getRootBase (asr);
11445                               
11446                               if (!sRef_similar (sRef_getBase (asr), thisref)) 
11447                                 {
11448                                   if (sRef_isUnique (base) || sRef_isOnly (base)
11449                                       || sRef_isKept (base)
11450                                       || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11451                                       || (sRef_isAddress (thisref) 
11452                                           && sRef_isLocalVar (sRef_getRootBase (thisref))))
11453                                     {
11454                                       ; /* okay, no error */
11455                                     }
11456                                   else
11457                                     {
11458                                       voptgenerror 
11459                                         (FLG_MAYALIASUNIQUE,
11460                                          message
11461                                          ("Parameter %d (%s) to function %s is declared %s but "
11462                                           "may be aliased externally by parameter %d (%s)",
11463                                           paramno, 
11464                                           exprNode_unparse (current),
11465                                           exprNode_unparse (fcn),
11466                                           alkind_unparse (uentry_getAliasKind (ucurrent)),
11467                                           iparamno, exprNode_unparse (icurrent)),
11468                                          current->loc);
11469                                     }
11470                                 }
11471                             }
11472                         }
11473                       else
11474                         {
11475                           voptgenerror 
11476                             (FLG_ALIASUNIQUE,
11477                              message
11478                              ("Parameter %d (%s) to function %s is declared %s but "
11479                               "is aliased externally by parameter %d (%s) through "
11480                               "alias %q",
11481                               paramno, 
11482                               exprNode_unparse (current),
11483                               exprNode_unparse (fcn),
11484                               alkind_unparse (uentry_getAliasKind (ucurrent)),
11485                               iparamno, exprNode_unparse (icurrent),
11486                               sRef_unparse (asr)),
11487                              current->loc);
11488                         }
11489                     }
11490                 } end_sRefSet_allElements;
11491               sRefSet_free (aliases);
11492             }
11493         }
11494     } end_exprNodeList_elements;
11495 }
11496
11497 long exprNode_getLongValue (exprNode e) 
11498 {
11499   long value;
11500   
11501   if (exprNode_hasValue (e) && multiVal_isInt (exprNode_getValue (e)))
11502     {
11503       value = multiVal_forceInt (exprNode_getValue (e));
11504     }
11505   else
11506     {
11507       value = 0; /* Unknown value */
11508     }
11509   
11510   return value;
11511 }
11512
11513 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11514 {
11515   /*
11516   ** Returns the location of the sequence point following e.
11517   **
11518   ** Only works for statements (for now).
11519   */
11520
11521   if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11522     lltok t = exprData_getUopTok (e->edata);
11523     return fileloc_copy(lltok_getLoc (t));
11524   } else {
11525     /* drl possible problem : warning fix
11526        llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11527     */
11528     return fileloc_undefined;
11529   }
11530  }
11531
11532 exprNode exprNode_createNew(ctype c)
11533 {
11534   exprNode ret;
11535
11536   ret = exprNode_createPlain (c);
11537
11538   return ret;
11539 }
11540
11541 bool exprNode_isInitBlock (exprNode e)
11542 {
11543   return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);
11544 }
11545
11546 /*drl 3/2/2003 moved this function out of constraint.c */
11547 exprNode exprNode_copyConstraints (/*@returned@*/ exprNode dst, exprNode src)
11548 {
11549     
11550   llassert (exprNode_isDefined (dst) );
11551   llassert (exprNode_isDefined (src) ); 
11552
11553   constraintList_free (dst->ensuresConstraints);
11554   constraintList_free (dst->requiresConstraints);
11555   constraintList_free (dst->trueEnsuresConstraints);
11556   constraintList_free (dst->falseEnsuresConstraints);
11557   
11558   dst->ensuresConstraints = constraintList_copy (src->ensuresConstraints);
11559   dst->requiresConstraints = constraintList_copy (src->requiresConstraints);
11560   dst->trueEnsuresConstraints = constraintList_copy (src->trueEnsuresConstraints);
11561   dst->falseEnsuresConstraints = constraintList_copy (src->falseEnsuresConstraints);
11562   return dst;
11563 }
11564
11565 void exprNode_revealState (exprNode e)
11566 {
11567   if (exprNode_isDefined (e)) {
11568     llmsg (message ("%s: State of %s: %s", fileloc_unparse (exprNode_loc (e)), 
11569                     exprNode_unparse (e), sRef_unparseFull (e->sref)));
11570   } else {
11571     llmsg (message ("%s: Reveal state undefined", fileloc_unparse (g_currentloc)));
11572   }
11573 }
This page took 1.122583 seconds and 5 git commands to generate.