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