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