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