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