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