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