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