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