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