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