]> andersk Git - splint.git/blob - src/exprNode.c
5f27cd8c8b2a3d091b8e9c0d1663115e75ec91ac
[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                                       if (optgenerror 
3311                                           (FLG_STATEMERGE,
3312                                            message
3313                                            ("Attributes merged in ensures clause in states that "
3314                                             "cannot be combined (%q is %q, %q is %q)%q",
3315                                             sRef_unparse (lastref),
3316                                             stateValue_unparseValue (sval, msinfo),
3317                                             sRef_unparse (fs),
3318                                             stateValue_unparseValue (tval, msinfo),
3319                                             cstring_isDefined (msg) ? 
3320                                             message (": %s", msg) : cstring_undefined),
3321                                            exprNode_loc (f)))
3322                                         {
3323                                           sRef_showMetaStateInfo (fs, key);
3324                                         }                   
3325                                     }
3326                                   
3327                                   stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3328                                   loc = exprNode_loc (arg);
3329                                 }
3330                               else
3331                                 {
3332                                   DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3333                                 }
3334                             }
3335                           else
3336                             {
3337                               sval = sRef_getMetaStateValue (fs, key);
3338                             }
3339                           
3340                           lastref = fs;
3341                           
3342                           if (stateValue_isError (sval))
3343                             {
3344                               /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3345                             }
3346                         
3347                           
3348                           paramno++;
3349                         }
3350                     }
3351                   else
3352                     {
3353                       msr = metaStateSpecifier_getSref (ms);
3354                   
3355                       
3356                       llassert (sRef_isParam (sRef_getRootBase (msr)));
3357                       fs = sRef_fixBaseParam (msr, args);
3358                       
3359                       if (stateValue_isDefined (sval))
3360                         {
3361                           /* Use combination table to merge old state value with new one: */
3362                           stateValue tval = sRef_getMetaStateValue (fs, key);
3363                           
3364                           if (stateValue_isDefined (tval))
3365                             {
3366                               stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3367                               cstring msg = cstring_undefined;
3368                               int nval = stateCombinationTable_lookup (sctable, 
3369                                                                        stateValue_getValue (sval), 
3370                                                                        stateValue_getValue (tval), 
3371                                                                        &msg);
3372                               DPRINTF (("Combining: %s + %s -> %d",
3373                                         stateValue_unparseValue (sval, msinfo),
3374                                         stateValue_unparseValue (tval, msinfo),
3375                                         nval));
3376                               
3377                               if (nval == stateValue_error)
3378                                 {
3379                                   if (optgenerror 
3380                                       (FLG_STATEMERGE,
3381                                        message
3382                                        ("Attributes merged in ensures clause in states that "
3383                                         "cannot be combined (%q is %q, %q is %q)%q",
3384                                         sRef_unparse (lastref),
3385                                         stateValue_unparseValue (sval, msinfo),
3386                                         sRef_unparse (fs),
3387                                         stateValue_unparseValue (tval, msinfo),
3388                                         cstring_isDefined (msg) 
3389                                         ? message (": %s", msg) : cstring_undefined),
3390                                        exprNode_loc (f)))
3391                                     {
3392                                       sRef_showMetaStateInfo (fs, key);
3393                                     }               
3394                                 }
3395                               
3396                               stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3397                             }
3398                           else
3399                             {
3400                               DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3401                             }
3402                         }
3403                       else
3404                         {
3405                           sval = sRef_getMetaStateValue (fs, key);
3406                         }
3407                       
3408                       lastref = fs;
3409                       
3410                       if (stateValue_isError (sval))
3411                         {
3412                           /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3413                         }
3414                     }
3415                 }
3416
3417               DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3418               
3419               if (stateValue_isDefined (sval))
3420                 {
3421                   sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3422                 }
3423               else
3424                 {
3425                   DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3426                 }
3427             } end_metaStateConstraintList_elements ;
3428
3429           metaStateConstraintList_free (mscl);
3430         }
3431     }
3432 }
3433
3434 static void
3435 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3436 {
3437   DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3438             exprNode_unparse (f), exprNodeList_unparse (args),
3439             uentry_unparseFull (le),
3440             stateClauseList_unparse (uentry_getStateClauseList (le))));
3441   
3442   if (uentry_isValid (le) && uentry_isFunction (le))
3443     {
3444       stateClauseList sclauses = uentry_getStateClauseList (le);
3445       
3446       if (stateClauseList_isDefined (sclauses))
3447         {
3448           DPRINTF (("Check requires: %s / %s / %s",
3449                     uentry_unparse (le),
3450                     exprNode_unparse (f), exprNodeList_unparse (args)));
3451           
3452           stateClauseList_elements (sclauses, cl) 
3453             {
3454               DPRINTF (("Check clause: %s / %s",
3455                         stateClause_unparse (cl),
3456                         bool_unparse (stateClause_hasRequires (cl))));
3457
3458               if (stateClause_hasRequires (cl))
3459                 {
3460                   sRefSet osrs = sRefSet_undefined;
3461                   sRefSet srs;
3462
3463                   if (stateClause_isGlobal (cl))
3464                     {
3465                       srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3466                       osrs = srs;
3467                     }
3468                   else
3469                     {
3470                       srs = stateClause_getRefs (cl);
3471                     }
3472
3473                   DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3474
3475                   if (stateClause_setsMetaState (cl))
3476                     {
3477                       qual q = stateClause_getMetaQual (cl);
3478                       annotationInfo ainfo = qual_getAnnotationInfo (q);
3479                       metaStateInfo minfo = annotationInfo_getState (ainfo);
3480                       cstring key = metaStateInfo_getName (minfo);
3481                       int mvalue = annotationInfo_getValue (ainfo);
3482                       
3483                       DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3484                       
3485                       sRefSet_elements (srs, sel)
3486                         {
3487                           sRef s = sRef_fixBaseParam (sel, args);
3488                           
3489                           if (sRef_isResult (sRef_getRootBase (sel)))
3490                             {
3491                               BADBRANCH;
3492                             }
3493                           else 
3494                             {
3495                               DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3496                                         sRef_unparseFull (sel), sRef_unparseFull (s),
3497                                         key, mvalue));
3498                               
3499                               if (!sRef_checkMetaStateValue (s, key, mvalue))
3500                                 {                       
3501                                   DPRINTF (("HERE: %s", sRef_unparse (s)));
3502                                   if (optgenerror 
3503                                       (FLG_STATETRANSFER,
3504                                        message
3505                                        ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3506                                         uentry_getName (le),
3507                                         sRef_isGlobalMarker (s) 
3508                                            ? message ("") 
3509                                            : message (" by %q", sRef_unparse (s)),
3510                                         stateValue_unparseValue (sRef_getMetaStateValue (s, key), 
3511                                                                  minfo),
3512                                         stateClause_unparse (cl)),
3513                                        exprNode_loc (f)))
3514                                     {
3515                                       sRef_showAliasInfo (s);
3516                                     }
3517                                   else
3518                                     {
3519                                       DPRINTF (("Error supressed!"));
3520                                       DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3521                                       DPRINTF (("Context supress: %s",
3522                                                 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3523                                     }
3524                                 }
3525                             }
3526                         } end_sRefSet_elements;
3527                     }
3528                   else
3529                     {
3530                       sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3531                       int eparam = stateClause_getStateParameter (cl);
3532                       
3533                       DPRINTF (("Reflect after clause: %s / %s", 
3534                                 stateClause_unparse (cl),
3535                                 sRefSet_unparse (srs)));
3536                       
3537                       sRefSet_elements (srs, sel)
3538                         {
3539                           sRef s;
3540                           
3541                           DPRINTF (("elements: %s", sRef_unparse (sel)));
3542                           DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3543                           
3544                           s = sRef_fixBaseParam (sel, args);
3545                           
3546                           DPRINTF (("elements: %s", sRef_unparse (s)));
3547                           DPRINTF (("elements: %s", sRef_unparseFull (s)));
3548                           
3549                           if (sRef_isResult (sRef_getRootBase (sel)))
3550                             {
3551                               ; /*@i423 what do we do about results */
3552                             }
3553                           else
3554                             {
3555                               DPRINTF (("Reflecting state clause on: %s / %s",
3556                                         sRef_unparse (sel), sRef_unparse (s)));
3557                               
3558                               modf (s, eparam, exprNode_loc (f));
3559                             }
3560                         } end_sRefSet_elements;
3561                     }
3562
3563                   sRefSet_free (osrs);
3564                 }
3565             } end_stateClauseList_elements ;        
3566         }
3567     }
3568 }
3569
3570 static /*@only@*/ exprNode
3571 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3572                   ctype t, /*@keep@*/ exprNodeList args)
3573 {
3574   /* requires f is a non-error exprNode, with type function */
3575   cstring fname = exprNode_unparse (f);
3576   uentry le = exprNode_getUentry (f);
3577   exprNode ret = exprNode_createPartialCopy (f);
3578   int special;
3579
3580   setCodePoint ();
3581
3582   DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3583
3584   ret->typ = ctype_getReturnType (t);
3585   ret->kind = XPR_CALL;
3586
3587   ret->edata = exprData_makeCall (f, args);
3588
3589   /*
3590   ** Order of these steps is very important!  
3591   **
3592   ** Must check for argument dependencies before messing up uses and sets.
3593   */
3594
3595   if (context_getFlag (FLG_EVALORDER))
3596     {
3597       exprNodeList_elements (args, current)
3598         {
3599           if (exprNode_isDefined (current))
3600             {
3601               exprNode_addUse (current, current->sref);
3602             }
3603         } end_exprNodeList_elements;
3604
3605       if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3606         {
3607           checkSequencing (f, args); 
3608         }
3609       
3610       exprNodeList_elements (args, current)
3611         {
3612           if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3613             {
3614               exprNode_addUse (ret, sRef_makeDerived (current->sref));
3615             }
3616         } end_exprNodeList_elements ;
3617     }
3618
3619   special = checkArgs (le, f, t, args, ret); 
3620   checkGlobMods (f, le, args, ret, special); 
3621   checkRequiresClause (le, f, args);
3622   setCodePoint ();
3623
3624   if (uentry_isValid (le)
3625       && (uentry_isFunction (le) 
3626           || (uentry_isVariable (le)
3627               && ctype_isFunction (uentry_getType (le)))))
3628     {
3629       exitkind exk = uentry_getExitCode (le);
3630
3631       /* f->typ is already set to the return type */
3632
3633       DPRINTF (("Function: %s", uentry_unparseFull (le)));
3634       ret->sref = uentry_returnedRef (le, args);
3635       DPRINTF (("Returned: %s / %s",
3636                 uentry_unparseFull (le),
3637                 sRef_unparseFull (ret->sref)));
3638       
3639       if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3640         {
3641           qual nullPred = uentry_nullPred (le);
3642
3643           if (qual_isTrueNull (nullPred))
3644             {
3645               exprNode arg = exprNodeList_head (args);
3646
3647               if (exprNode_isDefined (arg))
3648                 {
3649                   ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3650                 }
3651             }
3652           else if (qual_isFalseNull (nullPred))
3653             {
3654               exprNode arg = exprNodeList_head (args);
3655               
3656               if (exprNode_isDefined (arg))
3657                 {
3658                   ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3659                 }
3660             }
3661           else
3662             {
3663               llassert (qual_isUnknown (nullPred));
3664             }
3665         }
3666       
3667       if (exitkind_isConditionalExit (exk))
3668         {
3669           /*
3670           ** True exit is: 
3671           **    if (arg0) then { exit! } else { ; }
3672           ** False exit is:
3673           **    if (arg0) then { ; } else { exit! }
3674           */
3675
3676           exprNode firstArg;
3677
3678           llassert (!exprNodeList_isEmpty (args));
3679           firstArg = exprNodeList_head (args);
3680
3681           if (exprNode_isDefined (firstArg)
3682               && !guardSet_isEmpty (firstArg->guards))
3683             {
3684               usymtab_trueBranch (guardSet_undefined);
3685               usymtab_altBranch (guardSet_undefined);
3686               
3687               if (exitkind_isTrueExit (exk))
3688                 {
3689                   usymtab_popBranches (firstArg, 
3690                                        exprNode_makeMustExit (), 
3691                                        exprNode_undefined,
3692                                        TRUE, TRUEEXITCLAUSE);
3693                 }
3694               else
3695                 {
3696                   usymtab_popBranches (firstArg,
3697                                        exprNode_undefined,
3698                                        exprNode_makeMustExit (), 
3699                                        TRUE, FALSEEXITCLAUSE);
3700                 }
3701             }
3702
3703           ret->exitCode = XK_MAYEXIT;
3704         }
3705       else if (exitkind_mustExit (exk))
3706         {
3707           ret->exitCode = XK_MUSTEXIT;
3708         }
3709       else if (exitkind_couldExit (exk))
3710         {
3711           ret->exitCode = XK_MAYEXIT;
3712         }
3713       else
3714         {
3715           ;
3716         }
3717       
3718       if (cstring_equalLit (fname, "exit"))
3719         {
3720           if (exprNodeList_size (args) == 1)
3721             {
3722               exprNode arg = exprNodeList_head (args);
3723               
3724               if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3725                 {
3726                   long int val = multiVal_forceInt (exprNode_getValue (arg));
3727                   
3728                   if (val != 0)
3729                     {
3730                       voptgenerror
3731                         (FLG_EXITARG,
3732                          message 
3733                          ("Argument to exit has implementation defined behavior: %s",
3734                           exprNode_unparse (arg)),
3735                          exprNode_loc (arg));
3736                     }
3737                 }
3738             }
3739         }
3740     }
3741   else
3742     {
3743       ret->sref = defref;
3744       exprNode_checkSetAny (ret, uentry_rawName (le));
3745     }
3746
3747   DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3748   DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3749   reflectEnsuresClause (ret, le, f, args);
3750   setCodePoint ();
3751
3752   return (ret);
3753 }
3754
3755 /*
3756 ** this is yucky!  should keep the uentry as part of exprNode!
3757 */
3758
3759 uentry exprNode_getUentry (exprNode e)
3760 {
3761   if (exprNode_isError (e))
3762     {
3763       return uentry_undefined;
3764     }
3765   else
3766     {
3767       cstring s = exprNode_rootVarName (e);
3768       uentry ue = usymtab_lookupSafe (s);
3769
3770       return ue;
3771     }
3772 }
3773
3774 exprNode 
3775 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3776 {
3777   exprNode ret = exprNode_createPlain (ctype_unknown);
3778
3779   ret->kind = XPR_INITBLOCK;
3780   ret->edata = exprData_makeCall (exprNode_undefined, inits);
3781   ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3782
3783   return (ret);
3784 }
3785
3786 exprNode
3787 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3788 {
3789   ctype t;
3790
3791   setCodePoint ();
3792
3793   if (exprNode_isUndefined (f))
3794     {
3795       exprNode_free (f);
3796       exprNodeList_free (args);
3797       return exprNode_undefined;
3798     }
3799
3800   t = exprNode_getType (f);
3801
3802   if (sRef_isLocalVar (f->sref))
3803     {
3804       exprNode_checkUse (f, f->sref, f->loc);
3805
3806       if (sRef_possiblyNull (f->sref))
3807         {
3808           if (!usymtab_isGuarded (f->sref))
3809             {
3810               if (optgenerror (FLG_NULLDEREF,
3811                                message ("Function call using %s pointer %q", 
3812                                         sRef_nullMessage (f->sref),
3813                                         sRef_unparse (f->sref)),
3814                                f->loc))
3815                 {
3816                   sRef_showNullInfo (f->sref);
3817                   sRef_setNullError (f->sref);
3818                 }
3819             }
3820         }
3821     }
3822
3823   setCodePoint ();
3824
3825   if (ctype_isRealFunction (t))
3826     {
3827       exprNode ret = functionCallSafe (f, t, args);
3828       setCodePoint ();
3829       return ret;
3830     }
3831   else if (ctype_isUnknown (t))
3832     {
3833       exprNode ret = exprNode_createPartialCopy (f);
3834       cstring tstring;
3835
3836       setCodePoint ();
3837       
3838       ret->typ = t;
3839       exprNodeList_elements (args, current)
3840         {
3841           if (exprNode_isDefined (current))
3842             {
3843               exprNode_checkUse (ret, current->sref, ret->loc);
3844
3845               /* 
3846               ** also, anything derivable from current->sref may be used 
3847               */
3848
3849               exprNode_addUse (ret, sRef_makeDerived (current->sref));
3850               exprNode_mergeUSs (ret, current);
3851             }
3852         } end_exprNodeList_elements;
3853
3854       ret->edata = exprData_makeCall (f, args);
3855       ret->kind = XPR_CALL;
3856
3857       tstring = cstring_copy (exprNode_unparse (f));
3858
3859       cstring_markOwned (tstring);
3860       exprNode_checkSetAny (ret, tstring);
3861
3862       return (ret);
3863     }
3864   else
3865     {
3866       voptgenerror (FLG_TYPE,
3867                     message ("Call to non-function (type %t): %s", t, 
3868                              exprNode_unparse (f)),
3869                     f->loc);
3870       exprNode_free (f);
3871       exprNodeList_free (args);
3872
3873       return (exprNode_makeError ());
3874     }
3875 }
3876
3877 static exprNode
3878 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3879                          /*@only@*/ cstring f)
3880 {
3881   exprNode ret = exprNode_createPartialCopy (s);
3882
3883   ret->kind = XPR_FACCESS;
3884
3885   if (exprNode_isError (s))
3886     {
3887       ret->edata = exprData_makeField (s, f);
3888       return ret;
3889     }
3890   else
3891     {
3892       ctype t = exprNode_getType (s);
3893       ctype tr = ctype_realType (t);
3894
3895       checkMacroParen (s);
3896
3897       ret->edata = exprData_makeField (s, f);
3898
3899       if (ctype_isStructorUnion (tr))
3900         {
3901           uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3902
3903           if (uentry_isUndefined (tf))
3904             {
3905               voptgenerror (FLG_TYPE,
3906                             message ("Access non-existent field %s of %t: %s", f, t, 
3907                                      exprNode_unparse (ret)),
3908                             loc);
3909               /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
3910               return (ret);
3911             }
3912           else
3913             {
3914               uentry_setUsed (tf, exprNode_loc (ret));
3915
3916               ret->typ = uentry_getType (tf); 
3917               checkSafeUse (ret, s->sref);
3918               
3919               ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
3920               /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
3921               return (ret);
3922             }
3923         }
3924       else /* isStructorUnion */
3925         {
3926           if (ctype_isRealAbstract (tr))
3927             {
3928               voptgenerror
3929                 (FLG_ABSTRACT,
3930                  message ("Access field of abstract type (%t): %s.%s", 
3931                           t, exprNode_unparse (s), f),
3932                  loc);
3933               ret->typ = ctype_unknown;
3934             }
3935           else
3936             {
3937               if (ctype_isKnown (tr))
3938                 {
3939                   voptgenerror 
3940                     (FLG_TYPE,
3941                      message
3942                      ("Access field of non-struct or union (%t): %s.%s",
3943                       t, exprNode_unparse (s), f),
3944                      loc);
3945
3946                   ret->typ = ctype_unknown;
3947                 }
3948               else
3949                 {
3950                   cstring sn = cstring_copy (f);
3951                   
3952                   checkSafeUse (ret, s->sref);
3953                   cstring_markOwned (sn);
3954                   ret->sref = sRef_makeField (s->sref, sn);
3955                   return (ret);
3956                 }
3957             }
3958
3959           return (ret);
3960         }
3961     }
3962   BADEXIT;
3963 }
3964
3965 exprNode
3966 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
3967                       /*@only@*/ cstring f)
3968 {
3969   exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
3970   lltok_release (dot);
3971   return res;
3972 }
3973
3974 exprNode
3975 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
3976 {
3977   exprNode ret = exprNode_createPartialCopy (e);
3978
3979   ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
3980   ret->kind = XPR_PARENS;
3981   ret->edata = exprData_makeUop (e, lpar);
3982
3983   if (!exprNode_isError (e))
3984     {
3985       ret->exitCode = e->exitCode;
3986       ret->canBreak = e->canBreak;
3987       ret->mustBreak = e->mustBreak;
3988       ret->isJumpPoint = e->isJumpPoint;
3989       ret->sref = e->sref;
3990     }
3991
3992   return ret;
3993 }
3994
3995 static exprNode
3996 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3997                          /*@only@*/ cstring f)
3998 {
3999   exprNode ret = exprNode_createPartialCopy (s);
4000
4001   ret->edata = exprData_makeField (s, f);
4002   ret->kind = XPR_ARROW;
4003   
4004   if (exprNode_isError (s))
4005     {
4006       return (ret);
4007     }
4008   else
4009     {
4010       ctype t = exprNode_getType (s);
4011       ctype tr = ctype_realType (t);
4012       
4013       checkMacroParen (s);
4014       
4015       (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4016       
4017       if (ctype_isRealPointer (tr)) 
4018         {
4019           ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4020           
4021           if (ctype_isStructorUnion (b))
4022             {
4023               uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4024               
4025               if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4026                 {
4027                   if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4028                     {
4029                       if (optgenerror 
4030                           (FLG_NULLDEREF,
4031                            message ("Arrow access from %s pointer%q: %s", 
4032                                     sRef_nullMessage (s->sref),
4033                                     sRef_unparsePreOpt (s->sref),
4034                                     exprNode_unparse (ret)),
4035                            loc))
4036                         {
4037                           sRef_showNullInfo (s->sref);
4038                           sRef_setNullError (s->sref);
4039                         }
4040                     }
4041                 }
4042               
4043               if (uentry_isUndefined (fentry))
4044                 {
4045                   voptgenerror 
4046                     (FLG_TYPE,
4047                      message ("Access non-existent field %s of %t: %s", 
4048                               f, t, exprNode_unparse (ret)),
4049                      loc);
4050                   ret->typ = ctype_unknown;
4051                   return (ret);
4052                 }
4053               else
4054                 {
4055                   /*
4056                   ** was safeUse: shouldn't be safe!
4057                   **
4058                   ** to do rec->field
4059                   ** rec must be defined,
4060                   ** *rec must be allocated
4061                   ** rec->field need only be defined it if is an rvalue
4062                   */
4063                   
4064                   uentry_setUsed (fentry, exprNode_loc (ret));
4065                   ret->typ = uentry_getType (fentry);
4066                   
4067                   exprNode_checkUse (ret, s->sref, s->loc);
4068                   
4069                   /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4070                   ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4071                   return (ret);
4072                 }
4073             }
4074           else /* Pointer to something that is not a struct or union*/
4075             {
4076               if (ctype_isRealAbstract (tr))
4077                 {
4078                   ctype xrt = ctype_forceRealType (tr);
4079                   
4080                   voptgenerror 
4081                     (FLG_ABSTRACT,
4082                      message ("Arrow access field of abstract type (%t): %s->%s", 
4083                               t, exprNode_unparse (s), f),
4084                      loc);
4085                   
4086                   /*
4087                   ** Set the state correctly, as if the abstraction is broken.
4088                   */
4089                   
4090                   if (ctype_isRealPointer (xrt) &&
4091                       (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4092                        ctype_isStructorUnion (b)))
4093                     {
4094                       uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4095                       ret->typ = uentry_getType (fentry);
4096                       ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4097                     }
4098                   else
4099                     {
4100                       ret->typ = ctype_unknown;
4101                       ret->sref = sRef_undefined;
4102                     }
4103                 }
4104               else /* not a struct, union or abstract */
4105                 {
4106                   if (ctype_isUnknown (tr)) {
4107                     cstring sn = cstring_copy (f);
4108                     
4109                     DPRINTF (("Here: %s", exprNode_unparse (s)));
4110                     
4111                     exprNode_checkUse (ret, s->sref, s->loc);
4112                     exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4113                     
4114                     cstring_markOwned (sn);
4115                     ret->sref = sRef_makeArrow (s->sref, sn);
4116                     
4117                     ret->kind = XPR_ARROW;
4118                     return (ret);
4119                   } else {
4120                     voptgenerror 
4121                       (FLG_TYPE,
4122                        message ("Arrow access field of non-struct or union "
4123                                 "pointer (%t): %s->%s",
4124                                 t, exprNode_unparse (s), f),
4125                        loc);
4126                     
4127                     ret->typ = ctype_unknown;
4128                     ret->sref = sRef_undefined;
4129                   }
4130                 }
4131             }
4132         }
4133       else /* its not a pointer */
4134         {
4135           if (!ctype_isUnknown (tr))
4136             {
4137               voptgenerror 
4138                 (FLG_TYPE,
4139                  message ("Arrow access of non-pointer (%t): %s->%s",
4140                           t, exprNode_unparse (s), f),
4141                  loc);
4142               
4143               ret->typ = ctype_unknown;
4144               ret->sref = sRef_undefined;
4145             }
4146           else
4147             {
4148               cstring sn = cstring_copy (f);
4149               
4150               DPRINTF (("Here: %s", exprNode_unparse (s)));
4151               
4152               exprNode_checkUse (ret, s->sref, s->loc);
4153               exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4154               
4155               cstring_markOwned (sn);
4156               ret->sref = sRef_makeArrow (s->sref, sn);
4157               
4158               ret->kind = XPR_ARROW;
4159               return (ret);
4160             }
4161         }
4162       
4163       return (ret);
4164     }
4165   BADEXIT;
4166 }
4167
4168 exprNode
4169 exprNode_arrowAccess (/*@only@*/ exprNode s, 
4170                       /*@only@*/ lltok arrow,
4171                       /*@only@*/ cstring f)
4172 {
4173   exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4174   lltok_release (arrow);
4175   return res;
4176 }
4177
4178 /*
4179 ** only postOp's in C: i++ and i--
4180 */
4181
4182 exprNode
4183 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4184 {
4185   /* check modification also */
4186   /* cstring opname = lltok_unparse (op);*/
4187   ctype t;
4188   exprNode ret = exprNode_createPartialCopy (e);
4189
4190   ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4191   ret->kind = XPR_POSTOP;
4192   ret->edata = exprData_makeUop (e, op);
4193
4194   if (!exprNode_isDefined (e))
4195     {
4196       return ret;
4197     }
4198
4199   checkMacroParen (e);
4200
4201   exprNode_checkUse (ret, e->sref, e->loc);
4202   exprNode_checkSet (ret, e->sref);
4203
4204   t = exprNode_getType (e);
4205
4206   if (sRef_isUnsafe (e->sref))
4207     {
4208       voptgenerror (FLG_MACROPARAMS,
4209                     message ("Operand of %s is macro parameter (non-functional): %s%s", 
4210                              lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4211                     e->loc);
4212       sRef_makeSafe (e->sref);
4213       sRef_makeSafe (ret->sref);
4214     }
4215
4216   if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4217     {
4218       ret->typ = e->typ;
4219     }
4220   else
4221     {
4222       if (ctype_isRealAbstract (t))
4223         {
4224           voptgenerror 
4225             (FLG_ABSTRACT,
4226              message ("Operand of %s is abstract type (%t): %s",
4227                       lltok_unparse (op), t, exprNode_unparse (e)),
4228              e->loc);
4229         }
4230       else
4231         {
4232           voptgenerror 
4233             (FLG_TYPE,
4234              message ("Operand of %s is non-numeric (%t): %s",
4235                       lltok_unparse (op), t, exprNode_unparse (e)),
4236              e->loc);
4237         }
4238       ret->typ = ctype_unknown;
4239     }
4240
4241   /* if (ctype_isZero (t)) e->typ = ctype_int; */
4242
4243   exprNode_checkModify (e, ret);
4244
4245   /* added 7/11/2000 D.L */
4246   /*@i223*/ 
4247   /*DRL 6/8/01 I decided to disable all LCLint Warning here since the code 
4248     probably needs a rewrite any way */
4249
4250   /*@i65234@*/
4251   /*@ignore@*/
4252
4253   /* updateEnvironmentForPostOp (e); */
4254   
4255   /* start modifications */
4256   /* added by Seejo on 4/16/2000 */
4257   
4258   /* Arithmetic operations on pointers wil modify the size/len/null terminated 
4259      status */
4260   if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4261     
4262     ret->sref = sRef_copy (e->sref);
4263     
4264     /* Operator : ++ */
4265     if (lltok_getTok (op) == INC_OP) {
4266       if (sRef_getSize(e->sref) > 0) {
4267         
4268         sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4269         
4270         if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4271           /* Assumption: there is only 1 \0 in the buffer */
4272           /* This will not be correct if there are 2 \0's in the buffer */
4273           sRef_setNotNullTerminatedState(ret->sref);
4274           sRef_resetLen(ret->sref);
4275         } else {
4276           sRef_setNullTerminatedState(ret->sref);
4277           sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4278         }
4279         if (sRef_isNullTerminated (ret->sref))
4280           printf ("ret->sref is Null Terminated\n");
4281         else if (sRef_isPossiblyNullTerminated (ret->sref))
4282           printf ("ret->sref is Possibly Null Terminated\n");
4283         else if (sRef_isNotNullTerminated (ret->sref))
4284           printf ("ret->sref is Not Null Terminated\n");
4285       }
4286     }
4287     
4288     /* Operator : -- */
4289     if (lltok_getTok (op) == DEC_OP) {
4290       if (sRef_getSize(e->sref) >= 0) {
4291         sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4292         sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4293       }
4294     }
4295   }
4296   /*@end@*/
4297   /* end modifications */
4298
4299   return ret;
4300 }
4301
4302 exprNode
4303 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4304 {
4305   bool checkMod = FALSE;
4306   ctype te, tr;
4307   int opid = lltok_getTok (op);
4308   exprNode ret = exprNode_createSemiCopy (e);
4309
4310   exprNode_copySets (ret, e);
4311
4312   multiVal_free (ret->val);
4313   ret->val = multiVal_undefined;
4314   ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4315   ret->kind = XPR_PREOP;  
4316   ret->edata = exprData_makeUop (e, op);
4317   
4318   if (exprNode_isError (e))
4319     {
4320       return ret;
4321     }
4322   
4323   checkMacroParen (e);
4324   
4325   te = exprNode_getType (e);
4326   tr = ctype_realType (te);
4327   
4328   if (opid != TAMPERSAND)
4329     {
4330       exprNode_checkUse (ret, e->sref, e->loc);
4331       
4332       if (ctype_isRealAbstract (tr)
4333           && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4334         {
4335           if (optgenerror (FLG_ABSTRACT,
4336                            message ("Operand of %s is abstract type (%t): %s",
4337                                     lltok_unparse (op), tr,
4338                                     exprNode_unparse (ret)),
4339                            e->loc))
4340             {
4341               tr = te = ctype_unknown;
4342               ret->typ = ctype_unknown;
4343               sRef_setNullError (e->sref);
4344             }
4345         }
4346     }
4347   
4348   switch (opid)
4349     {
4350     case INC_OP:
4351     case DEC_OP:                /* should also check modification! */
4352       if (sRef_isMacroParamRef (e->sref))
4353         {
4354           voptgenerror 
4355             (FLG_MACROPARAMS,
4356              message ("Operand of %s is macro parameter (non-functional): %s", 
4357                       lltok_unparse (op), exprNode_unparse (ret)),
4358              e->loc);
4359         }
4360       else
4361         {
4362           exprNode_checkSet (ret, e->sref);
4363         }
4364       
4365       if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4366         {
4367         }
4368       else
4369         {
4370           if (context_msgStrictOps ())
4371             {
4372               voptgenerror 
4373                 (FLG_STRICTOPS,
4374                  message ("Operand of %s is non-numeric (%t): %s",
4375                           lltok_unparse (op), te, exprNode_unparse (ret)),
4376                  e->loc);
4377             }
4378           ret->typ = ctype_int;
4379         }
4380
4381         /* start modifications */
4382         /* added by Seejo on 4/16/2000 */
4383
4384         /* Arithmetic operations on pointers wil modify the size/len/null terminated 
4385                  status */
4386         if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4387
4388                 ret->sref = sRef_copy (e->sref);
4389
4390                 /* Operator : ++ */
4391                 if (lltok_getTok (op) == INC_OP) {
4392                         if (sRef_getSize(e->sref) > 0) {
4393
4394                                 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4395
4396                                 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4397                                         /* Assumption: there is only 1 \0 in the buffer */
4398                                         /* This will not be correct if there are 2 \0's in the buffer */
4399                                         sRef_setNotNullTerminatedState(ret->sref);
4400                                         sRef_resetLen (ret->sref);
4401                                 } else {
4402                                         sRef_setNullTerminatedState(ret->sref);
4403                                         sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4404                                 }
4405                         }
4406                 }
4407
4408                 /* Operator : -- */
4409                 if (lltok_getTok (op) == DEC_OP) {
4410                         if (sRef_getSize(e->sref) >= 0) {
4411                                 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4412                                 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4413                         }
4414                 }
4415         }
4416
4417         /* end modifications */    
4418
4419       checkMod = TRUE;
4420       break;
4421       
4422     case TMINUS:
4423     case TPLUS:
4424       if (ctype_isForceRealNumeric (&tr))
4425         {
4426           if (opid == TMINUS)
4427             {
4428               ret->val = multiVal_invert (exprNode_getValue (e));
4429             }
4430           else
4431             {
4432               ret->val = multiVal_copy (exprNode_getValue (e));
4433             }
4434         }
4435       else
4436         {
4437           if (context_msgStrictOps ())
4438             {
4439               voptgenerror 
4440                 (FLG_STRICTOPS,
4441                  message ("Operand of %s is non-numeric (%t): %s",
4442                           lltok_unparse (op), te, exprNode_unparse (ret)),
4443                  e->loc);
4444             }
4445
4446           ret->typ = ctype_int;
4447         }
4448       break;
4449       
4450     case TEXCL:         /* maybe this should be restricted */
4451       guardSet_flip (ret->guards);      
4452
4453       if (ctype_isRealBool (te) || ctype_isUnknown (te))
4454         {
4455          ;
4456         }
4457       else
4458         {
4459           if (ctype_isRealPointer (tr))
4460             {
4461               if (sRef_isKnown (e->sref))
4462                 {
4463                   ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4464                 }
4465               
4466               voptgenerror2n
4467                 (FLG_BOOLOPS, FLG_PTRNEGATE,
4468                  message ("Operand of %s is non-boolean (%t): %s",
4469                           lltok_unparse (op), te, exprNode_unparse (ret)),
4470                  e->loc);
4471             }
4472           else
4473             {
4474               voptgenerror
4475                 (FLG_BOOLOPS,
4476                  message ("Operand of %s is non-boolean (%t): %s",
4477                           lltok_unparse (op), te, exprNode_unparse (ret)),
4478                  e->loc);
4479             }
4480           
4481           ret->typ = ctype_bool;
4482         }
4483       break;
4484       
4485     case TTILDE:
4486       if (ctype_isForceRealInt (&tr))
4487         {
4488         }
4489       else
4490         {
4491           if (context_msgStrictOps ())
4492             {
4493               voptgenerror 
4494                 (FLG_STRICTOPS,
4495                  message ("Operand of %s is non-integer (%t): %s",
4496                           lltok_unparse (op), te, exprNode_unparse (ret)), 
4497                  e->loc);
4498             }
4499
4500           if (ctype_isInt (e->typ))
4501             {
4502               ret->typ = e->typ;
4503             }
4504           else
4505             {
4506               ret->typ = ctype_int;
4507             }
4508         }       
4509       break;
4510       
4511     case TAMPERSAND:
4512       ret->typ = ctype_makePointer (e->typ);
4513
4514       if (sRef_isKnown (e->sref))
4515         {
4516           ret->sref = sRef_makeAddress (e->sref);
4517         }
4518       
4519       break;
4520       
4521     case TMULT:
4522       
4523       if (ctype_isAP (tr))
4524         {
4525           ret->typ = ctype_baseArrayPtr (e->typ);
4526         }
4527       else
4528         {
4529           if (ctype_isKnown (te))
4530             {
4531               if (ctype_isFunction (te))
4532                 {
4533                   ret->typ = e->typ;
4534
4535                   voptgenerror
4536                     (FLG_FCNDEREF,
4537                      message ("Dereference of function type (%t): %s",
4538                               te, exprNode_unparse (ret)),
4539                      e->loc);
4540                 }
4541               else
4542                 {
4543                   voptgenerror (FLG_TYPE,
4544                                 message ("Dereference of non-pointer (%t): %s",
4545                                          te, exprNode_unparse (ret)),
4546                                 e->loc);
4547                   ret->typ = ctype_unknown;
4548                 }
4549             }
4550           else
4551             {
4552               ret->typ = ctype_unknown;
4553             }
4554           
4555         }
4556       
4557       if (sRef_isKnown (e->sref))
4558         {
4559           if (sRef_possiblyNull (e->sref))
4560             {
4561               if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4562                 {
4563                   if (optgenerror 
4564                       (FLG_NULLDEREF,
4565                        message ("Dereference of %s pointer %q: %s", 
4566                                 sRef_nullMessage (e->sref),
4567                                 sRef_unparse (e->sref),
4568                                 exprNode_unparse (ret)),
4569                        e->loc))
4570                     {
4571                       sRef_showNullInfo (e->sref);
4572                       sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4573                     }
4574                 }
4575             }
4576           
4577           ret->sref = sRef_makePointer (e->sref);
4578         }
4579       break;
4580       
4581     default:
4582       llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4583     }
4584
4585   if (checkMod)
4586     {
4587       exprNode_checkModify (e, ret);
4588     }
4589
4590   return ret;
4591 }
4592
4593 /*
4594 ** any reason to disallow sizeof (abstract type) ?
4595 */
4596
4597 /*
4598 ** used by both sizeof
4599 */
4600
4601 static
4602 ctype sizeof_resultType (void)
4603 {
4604   static ctype sizet = ctype_unknown;
4605
4606   if (ctype_isUnknown (sizet))
4607     {
4608       if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4609         {
4610           sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4611         }
4612       else
4613         {
4614                   sizet = ctype_ulint;
4615         }
4616     }
4617   return sizet;
4618 }
4619
4620 exprNode
4621 exprNode_sizeofType (/*@only@*/ qtype qt)
4622 {
4623   exprNode ret = exprNode_create (sizeof_resultType ());
4624   ctype ct = qtype_getType (qt);
4625
4626   ret->kind = XPR_SIZEOFT;
4627   ret->edata = exprData_makeSizeofType (qt);
4628
4629   voptgenerror (FLG_SIZEOFTYPE,
4630                 message ("Parameter to sizeof is type %s: %s",
4631                          ctype_unparse (ct),
4632                          exprNode_unparse (ret)),
4633                 ret->loc);
4634   
4635   return (ret);
4636 }
4637
4638 exprNode
4639 exprNode_alignofType (/*@only@*/ qtype qt)
4640 {
4641   exprNode ret = exprNode_create (sizeof_resultType ());
4642   ctype ct = qtype_getType (qt);
4643
4644   ret->kind = XPR_ALIGNOFT;
4645   ret->edata = exprData_makeSizeofType (qt);
4646
4647   voptgenerror (FLG_SIZEOFTYPE,
4648                 message ("Parameter to alignof is type %s: %s",
4649                          ctype_unparse (ct),
4650                          exprNode_unparse (ret)),
4651                 ret->loc);
4652   
4653   return (ret);
4654 }
4655
4656 exprNode exprNode_offsetof (qtype qt, cstringList s)
4657 {
4658   exprNode ret = exprNode_create (sizeof_resultType ());
4659   ctype ct = qtype_getType (qt);
4660
4661   ret->kind = XPR_OFFSETOF;
4662   ret->edata = exprData_makeOffsetof (qt, s);
4663
4664   if (!ctype_isRealSU (ct))
4665     {
4666       voptgenerror (FLG_TYPE,
4667                     message ("First parameter to offsetof is not a "
4668                              "struct or union type (type %s): %s",
4669                              ctype_unparse (ct),
4670                              exprNode_unparse (ret)),
4671                     ret->loc);
4672     }
4673   else
4674     {
4675       ctype lt = ct;
4676
4677       cstringList_elements (s, el) {
4678         uentryList fields;
4679         uentry fld;
4680
4681         if (ctype_isUndefined (lt))
4682           {
4683             break;
4684           } 
4685         else if (!ctype_isRealSU (lt))
4686           {
4687             voptgenerror (FLG_TYPE,
4688                           message ("Inner offsetof type is not a "
4689                                    "struct or union type (type %s before field %s): %s",
4690                                    ctype_unparse (lt), el,
4691                                    exprNode_unparse (ret)),
4692                           ret->loc);
4693             break;
4694           }
4695         else 
4696           {
4697             fields = ctype_getFields (ctype_realType (lt));
4698             fld = uentryList_lookupField (fields, el);
4699             DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4700             
4701             if (uentry_isUndefined (fld))
4702               {
4703                 if (ctype_equal (lt, ct)) {
4704                   voptgenerror (FLG_TYPE,
4705                                 message ("Field %s in offsetof is not the "
4706                                          "name of a field of %s: %s",
4707                                          el,
4708                                          ctype_unparse (ct),
4709                                          exprNode_unparse (ret)),
4710                                 ret->loc);
4711                 } else {
4712                   voptgenerror (FLG_TYPE,
4713                                 message ("Deep field %s in offsetof is not the "
4714                                          "name of a field of %s: %s",
4715                                          el,
4716                                          ctype_unparse (lt),
4717                                          exprNode_unparse (ret)),
4718                                 ret->loc);
4719                 }
4720               }
4721             else 
4722               {
4723                 lt = uentry_getType (fld);
4724               }
4725           }
4726       } end_cstringList_elements;
4727
4728       /* Should report error if its a bit field - behavior is undefined! */
4729     }
4730   
4731   return (ret);
4732 }
4733
4734 /*@only@*/ exprNode
4735 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4736 {
4737   exprNode ret;
4738
4739   if (exprNode_isUndefined (e))
4740     {
4741       ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4742       ret->edata = exprData_makeSingle (e);
4743       ret->typ = sizeof_resultType ();
4744       ret->kind = XPR_SIZEOF;
4745     }
4746   else
4747     {
4748       uentry u = exprNode_getUentry (e);
4749
4750       ret = exprNode_createPartialCopy (e);
4751       ret->edata = exprData_makeSingle (e);
4752
4753       ret->typ = sizeof_resultType ();
4754       ret->kind = XPR_SIZEOF;
4755
4756       if (uentry_isValid (u) 
4757           && uentry_isRefParam (u)
4758           && ctype_isRealArray (uentry_getType (u)))
4759         {
4760           voptgenerror
4761             (FLG_SIZEOFFORMALARRAY,
4762              message ("Parameter to sizeof is an array-type function parameter: %s",
4763                       exprNode_unparse (ret)),
4764              ret->loc);
4765         }
4766     }
4767
4768   /*
4769   ** sizeof (x) doesn't "really" use x
4770   */
4771
4772   return (ret);
4773 }
4774
4775 /*@only@*/ exprNode
4776 exprNode_alignofExpr (/*@only@*/ exprNode e)
4777 {
4778   exprNode ret;
4779
4780   if (exprNode_isUndefined (e))
4781     {
4782       ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4783     }
4784   else
4785     {
4786       ret = exprNode_createPartialCopy (e);
4787     }
4788
4789   ret->edata = exprData_makeSingle (e);
4790   ret->typ = sizeof_resultType ();
4791   ret->kind = XPR_ALIGNOF;
4792   
4793   /*
4794   ** sizeof (x) doesn't "really" use x
4795   */
4796
4797   return (ret);
4798 }
4799
4800 /*@only@*/ exprNode
4801 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4802 {
4803   ctype c;
4804   ctype t;
4805   exprNode ret;
4806
4807   if (exprNode_isError (e))
4808     {
4809       qtype_free (q);
4810       lltok_release (tok);
4811       return exprNode_undefined;
4812     }
4813
4814   checkMacroParen (e);
4815
4816   c = qtype_getType (q);
4817   t = exprNode_getType (e);
4818
4819   ret = exprNode_createPartialCopy (e);
4820   
4821   ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4822   ret->typ = c;
4823   ret->kind = XPR_CAST;
4824   ret->edata = exprData_makeCast (tok, e, q);
4825
4826   if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4827     {
4828       /* 
4829       ** This is a bit of a hack to avoid a problem
4830       ** when the code does,
4831       **          (some other struct) x
4832       **          ...
4833       **          x->field
4834       */
4835
4836       ret->sref = sRef_copy (e->sref);
4837       usymtab_addForceMustAlias (ret->sref, e->sref);
4838       sRef_setTypeFull (ret->sref, c);
4839       DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4840                 sRef_unparseFull (ret->sref)));
4841     }
4842   else
4843     {
4844       ret->sref = e->sref;
4845       sRef_setTypeFull (ret->sref, c);
4846       DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4847     }
4848
4849   /*
4850   ** we allow
4851   **       abstract  -> void
4852   **              0 <-> abstract * 
4853   **         void * <-> abstract *  (if FLG_ABSTVOIDP)
4854   **     abstract * <-> void *      (if FLG_ABSTVOIDP)
4855   */
4856
4857   if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4858     {
4859       ;
4860     }
4861   else if (ctype_isRealAP (c)) /* casting to array or pointer */
4862     {
4863       ctype bc = ctype_getBaseType (c);
4864       ctype bt = ctype_getBaseType (t);
4865       ctype rt = ctype_realType (t);
4866
4867       if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4868           && (ctype_isArrayPtr (rt)
4869               && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4870         {
4871           voptgenerror
4872             (FLG_CASTFCNPTR,
4873              message ("Cast from function pointer type (%t) to "
4874                       "non-function pointer (%t): %s",
4875                       c, t, exprNode_unparse (ret)),
4876              e->loc);     
4877         }
4878
4879       if (!ctype_isFunction (ctype_baseArrayPtr (c))
4880           && (ctype_isArrayPtr (rt)
4881               && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4882         {
4883           voptgenerror
4884             (FLG_CASTFCNPTR,
4885              message ("Cast from non-function pointer type (%t) to "
4886                       "function pointer (%t): %s",
4887                       c, t, exprNode_unparse (ret)),
4888              e->loc);     
4889         }
4890
4891       if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4892           !(ctype_isRealAbstract (bc)
4893             && context_hasAccess (ctype_typeId (bc))))
4894         {
4895          ; /* okay to cast zero */
4896         }
4897       else
4898         {
4899           if (ctype_isRealAbstract (bc)
4900               && !context_hasAccess (ctype_typeId (bc)))
4901             {
4902               if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4903                 {
4904                   vnoptgenerror
4905                     (FLG_ABSTVOIDP,
4906                      message ("Cast to underlying abstract type %t: %s",
4907                               c, exprNode_unparse (ret)),
4908                      e->loc);
4909                 }
4910               else
4911                 {
4912                   voptgenerror
4913                     (FLG_ABSTRACT,
4914                      message ("Cast to underlying abstract type %t: %s",
4915                               c, exprNode_unparse (ret)),
4916                      e->loc);     
4917                 }
4918             }
4919
4920           if (ctype_isRealAbstract (bt)
4921               && !context_hasAccess (ctype_typeId (bt)))
4922             {
4923               if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
4924                 {
4925                   vnoptgenerror
4926                     (FLG_ABSTVOIDP,
4927                      message ("Cast from underlying abstract type %t: %s",
4928                               t, exprNode_unparse (ret)),
4929                      e->loc);
4930                 }
4931               else
4932                 {
4933                   voptgenerror
4934                     (FLG_ABSTRACT,
4935                      message ("Cast from underlying abstract type %t: %s",
4936                               t, exprNode_unparse (ret)),
4937                      e->loc);
4938                 }
4939             }
4940         }
4941     }
4942   else
4943     {
4944       ctype bt = ctype_realType (ctype_getBaseType (t));
4945       ctype bc = ctype_realType (ctype_getBaseType (c));
4946
4947       if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
4948         {
4949           if (ctype_match (c, t))
4950             {
4951               if (ctype_equal (c, t))
4952                 {
4953                   voptgenerror
4954                     (FLG_TYPE, 
4955                      message ("Redundant cast involving abstract type %t: %s",
4956                               bt, exprNode_unparse (ret)),
4957                      e->loc);
4958                 }
4959             }
4960           else
4961             {
4962               voptgenerror
4963                 (FLG_ABSTRACT,
4964                  message ("Cast from abstract type %t: %s", 
4965                           bt, exprNode_unparse (ret)),
4966                  e->loc);
4967             }
4968         }
4969       
4970       if (ctype_isAbstract (bc) 
4971           && !context_hasAccess (ctype_typeId (bc)))
4972         {
4973           if (ctype_match (c, t))
4974             {
4975              ;
4976             }
4977           else
4978             {
4979               DPRINTF (("No access to: %s / %d",
4980                         ctype_unparse (bc), ctype_typeId (bc)));
4981               DPRINTF (("Context %s %s",
4982                         bool_unparse (context_inFunctionLike ()),
4983                         context_unparse ()));
4984               voptgenerror 
4985                 (FLG_ABSTRACT,
4986                  message ("Cast to abstract type %t: %s", bc, 
4987                           exprNode_unparse (ret)),
4988                  e->loc);
4989             }
4990         }
4991     }
4992
4993   if (ctype_isAbstract (c))
4994     {
4995       if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
4996         {
4997           /* okay, cast exposed to abstract */
4998           sRef_clearExKindComplete (ret->sref, fileloc_undefined);
4999         }
5000       else 
5001         {
5002           if (ctype_isVisiblySharable (t) 
5003               && sRef_isExternallyVisible (e->sref)
5004               && !(ctype_isAbstract (t) 
5005                    && context_hasAccess (ctype_typeId (t))))
5006             {
5007               voptgenerror 
5008                 (FLG_CASTEXPOSE,
5009                  message ("Cast to abstract type from externally visible "
5010                           "mutable storage exposes rep of %s: %s",
5011                           ctype_unparse (c),
5012                           exprNode_unparse (e)),
5013                  e->loc);
5014             }
5015         }
5016     }
5017
5018   return (ret);
5019 }
5020
5021 static bool
5022 evaluationOrderUndefined (lltok op)
5023 {
5024   int opid = lltok_getTok (op);
5025
5026   return (opid != AND_OP && opid != OR_OP);
5027 }
5028
5029 static bool checkIntegral (/*@notnull@*/ exprNode e1, 
5030                            /*@notnull@*/ exprNode e2, 
5031                            /*@notnull@*/ exprNode ret, 
5032                            lltok op)
5033 {
5034   bool error = FALSE;
5035
5036   ctype te1 = exprNode_getType (e1);
5037   ctype te2 = exprNode_getType (e2);
5038
5039   ctype tr1 = ctype_realishType (te1);
5040   ctype tr2 = ctype_realishType (te2);
5041   
5042   if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5043     {
5044       ;
5045     }
5046   else
5047     {
5048       if (context_msgStrictOps ())
5049         {
5050           if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5051             {
5052               if (ctype_sameName (te1, te2))
5053                 {
5054                   error = optgenerror 
5055                     (FLG_STRICTOPS,
5056                      message ("Operands of %s are non-integer (%t): %s",
5057                               lltok_unparse (op), te1,
5058                               exprNode_unparse (ret)),
5059                      e1->loc);
5060                 }
5061               else
5062                 {
5063                   error = optgenerror 
5064                     (FLG_STRICTOPS,
5065                      message ("Operands of %s are non-integers (%t, %t): %s",
5066                               lltok_unparse (op), te1, te2,
5067                               exprNode_unparse (ret)),
5068                      e1->loc);
5069                 }
5070             }
5071           else if (!ctype_isInt (tr1))
5072             {
5073               error = optgenerror 
5074                 (FLG_STRICTOPS,
5075                  message ("Left operand of %s is non-integer (%t): %s",
5076                           lltok_unparse (op), te1, exprNode_unparse (ret)),
5077                  e1->loc);
5078             }
5079           else
5080             /* !ctype_isInt (te2) */
5081             {
5082               error = optgenerror 
5083                 (FLG_STRICTOPS,
5084                  message ("Right operand of %s is non-integer (%t): %s",
5085                           lltok_unparse (op), te2, exprNode_unparse (ret)),
5086                  e2->loc);
5087             }
5088         }
5089     }
5090
5091   return !error;
5092 }
5093
5094 /*
5095 ** returns exprNode representing e1 op e2
5096 **
5097 ** uses msg if there are errors
5098 ** can be used for both assignment ops and regular ops
5099 **
5100 ** modifies e1
5101 */
5102
5103 static /*@only@*/ /*@notnull@*/ exprNode
5104 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2, 
5105                  /*@keep@*/ lltok op)
5106 {
5107   ctype te1, te2, tr1, tr2, tret;
5108   int opid = lltok_getTok (op);
5109   bool hasError = FALSE;
5110   exprNode ret;
5111
5112   if (exprNode_isError (e1))
5113     {
5114       ret = exprNode_createPartialNVCopy (e2);
5115     }
5116   else
5117     {
5118       ret = exprNode_createPartialNVCopy (e1);    
5119     }
5120
5121   ret->val = multiVal_undefined;
5122   ret->kind = XPR_OP;
5123   ret->edata = exprData_makeOp (e1, e2, op);
5124
5125   if (exprNode_isError (e1) || exprNode_isError (e2))
5126     {
5127       if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5128           || opid == EQ_OP || opid == NE_OP 
5129           || opid == AND_OP || opid == OR_OP)
5130         {
5131           ret->typ = ctype_bool;
5132         }
5133
5134       if (exprNode_isDefined (e1))
5135         {
5136           exprNode_checkUse (ret, e1->sref, e1->loc);  
5137         }
5138
5139       if (exprNode_isDefined (e2))
5140         {
5141           exprNode_mergeUSs (ret, e2);
5142           exprNode_checkUse (ret, e2->sref, e2->loc);  
5143         }
5144
5145       return ret;
5146     }
5147
5148   tret = ctype_unknown;
5149   te1 = exprNode_getType (e1);
5150   DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5151
5152   te2 = exprNode_getType (e2);
5153
5154   tr1 = ctype_realishType (te1);
5155   tr2 = ctype_realishType (te2);
5156
5157   if (opid == OR_OP)
5158     {
5159       ret->guards = guardSet_or (ret->guards, e2->guards);
5160     }
5161   else if (opid == AND_OP)
5162     {
5163       ret->guards = guardSet_and (ret->guards, e2->guards);
5164     }
5165   else
5166     {
5167       /* no guards */
5168     }
5169
5170   if (opid == EQ_OP || opid == NE_OP)
5171     {
5172       exprNode temp1 = e1, temp2 = e2;
5173
5174       /* could do NULL == x */
5175       
5176       if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5177         {
5178           temp1 = e2; temp2 = e1;
5179         }
5180
5181       if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5182         {
5183           reflectNullTest (temp1, (opid == NE_OP));
5184           guardSet_free (ret->guards);
5185           ret->guards = guardSet_copy (temp1->guards);
5186         }
5187     }
5188
5189   if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5190       || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5191     {
5192       tret = ctype_bool; 
5193     }
5194   
5195   if (anyAbstract (tr1, tr2) &&
5196       (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) && 
5197          (opid == AND_OP || opid == OR_OP 
5198           || opid == EQ_OP || opid == NE_OP))))
5199     {
5200       abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5201     }
5202   else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5203     {
5204       /* unknown types, no comparisons possible */
5205     }
5206   else
5207     {
5208       switch (opid)
5209         {
5210         case TMULT:             /* multiplication and division:           */
5211         case TDIV:              /*                                        */
5212         case MUL_ASSIGN:        /*    numeric, numeric -> numeric         */
5213         case DIV_ASSIGN:        /*                                        */
5214           
5215           tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5216           break;
5217           
5218         case TPLUS:             /* addition and subtraction:               */
5219         case TMINUS:            /*    pointer, int     -> pointer          */
5220         case SUB_ASSIGN:        /*    int, pointer     -> pointer          */
5221         case ADD_ASSIGN:        /*    numeric, numeric -> numeric          */
5222           
5223           tr1 = ctype_fixArrayPtr (tr1);
5224
5225           if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5226               && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5227             {
5228               /* pointer + int */
5229
5230               if (context_msgPointerArith ())
5231                 {
5232                   voptgenerror
5233                     (FLG_POINTERARITH,
5234                      message ("Pointer arithmetic (%t, %t): %s", 
5235                               te1, te2, exprNode_unparse (ret)),
5236                      e1->loc);
5237                 }
5238
5239               /*
5240               ** Swap terms so e1 is always the pointer
5241               */
5242
5243               if (ctype_isRealPointer (tr1))
5244                 {
5245                   ;
5246                 }
5247               else
5248                 {
5249                   exprNode_swap (e1, e2);
5250                 }
5251
5252
5253               if (sRef_possiblyNull (e1->sref)
5254                   && !usymtab_isGuarded (e1->sref))
5255                 {
5256                   voptgenerror
5257                     (FLG_NULLPOINTERARITH,
5258                      message ("Pointer arithmetic involving possibly "
5259                               "null pointer %s: %s", 
5260                               exprNode_unparse (e1), 
5261                               exprNode_unparse (ret)),
5262                      e1->loc);
5263                 }
5264
5265               ret->sref = sRef_copy (e1->sref);
5266
5267               /* start modifications */
5268               /* added by Seejo on 4/16/2000 */
5269
5270               /* Arithmetic operations on pointers wil modify the size/len/null terminated 
5271                  status */
5272               if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5273                 int val;
5274                 /*drl 1-4-2001
5275                   added ugly fixed to stop
5276                   program from crashing on point + int +int
5277                   one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5278                 
5279                 if (!multiVal_isInt (e2->val) )
5280                   break;
5281                 /*end drl*/
5282                 
5283                 val = (int) multiVal_forceInt (e2->val);
5284                 
5285                 /* Operator : + or += */
5286                 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5287                   if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by 
5288                                                          val should not result in a 
5289                                                          size < 0 (size = 0 is ok !) */
5290                     
5291                     sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5292                     
5293                     if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5294                       sRef_setNotNullTerminatedState(ret->sref);
5295                       sRef_resetLen (ret->sref);
5296                     } else {
5297                       sRef_setNullTerminatedState(ret->sref);
5298                       sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5299                     }
5300                   }
5301                 }
5302                 
5303                 /* Operator : - or -= */
5304                 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5305                   if (sRef_getSize(e1->sref) >= 0) {
5306                     sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5307                     sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5308                   }
5309                 }
5310               }
5311               
5312               /* end modifications */  
5313
5314               sRef_setNullError (ret->sref);
5315
5316               /*
5317               ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5318               ** since is points to storage that should not be deallocated
5319               ** through this pointer.
5320               */
5321
5322               if (sRef_isOnly (ret->sref) 
5323                   || sRef_isFresh (ret->sref)) 
5324                 {
5325                   sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5326                 }
5327               
5328               tret = e1->typ;
5329             }
5330           else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1)) 
5331                    && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5332             {
5333               if (context_msgPointerArith ())
5334                 {
5335                   voptgenerror 
5336                     (FLG_POINTERARITH,
5337                      message ("Pointer arithmetic (%t, %t): %s", 
5338                               te1, te2, exprNode_unparse (ret)),
5339                      e1->loc);
5340                 }
5341
5342               if (sRef_possiblyNull (e1->sref)
5343                   && !usymtab_isGuarded (e1->sref))
5344                 {
5345                   voptgenerror
5346                     (FLG_NULLPOINTERARITH,
5347                      message ("Pointer arithmetic involving possibly "
5348                               "null pointer %s: %s", 
5349                               exprNode_unparse (e2), 
5350                               exprNode_unparse (ret)),
5351                      e2->loc);
5352                 }
5353
5354               ret->sref = sRef_copy (e2->sref);
5355
5356                   /* start modifications */
5357                   /* added by Seejo on 4/16/2000 */
5358
5359                   /* Arithmetic operations on pointers wil modify the size/len/null terminated 
5360                                  status */
5361
5362             if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5363               int val = (int) multiVal_forceInt (e1->val);
5364               
5365               /* Operator : + or += */
5366               if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5367                 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by 
5368                                                        val should not result in a 
5369                                                        size < 0 (size = 0 is ok !) */
5370                   
5371                   sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5372                   
5373                   if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5374                     sRef_setNotNullTerminatedState(ret->sref);
5375                     sRef_resetLen (ret->sref);
5376                   } else {
5377                     sRef_setNullTerminatedState(ret->sref);
5378                     sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5379                   }
5380                 }
5381               }
5382               
5383               /* Operator : - or -= */
5384               if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5385                 if (sRef_getSize(e2->sref) >= 0) {
5386                   sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5387                   sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5388                 }
5389               }
5390             }
5391             
5392             /* end modifications */
5393             
5394             sRef_setNullError (ret->sref);
5395             
5396             /*
5397             ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5398             ** since is points to storage that should not be deallocated
5399             ** through this pointer.
5400             */
5401             
5402             if (sRef_isOnly (ret->sref) 
5403                 || sRef_isFresh (ret->sref)) {
5404               sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5405             }
5406             
5407             tret = e2->typ;
5408             ret->sref = e2->sref;
5409             }
5410           else
5411             {
5412               tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5413             }
5414           
5415           break;
5416
5417         case LEFT_ASSIGN:   /* Shifts: should be unsigned values */
5418         case RIGHT_ASSIGN:
5419         case LEFT_OP:
5420         case RIGHT_OP:
5421         case TAMPERSAND:    /* bitwise & */
5422         case AND_ASSIGN:       
5423         case TCIRC:         /* ^ (XOR) */
5424         case TBAR:
5425         case XOR_ASSIGN:
5426         case OR_ASSIGN:
5427           {
5428             bool reported = FALSE;
5429             flagcode code = FLG_BITWISEOPS;
5430             
5431             if (opid == LEFT_OP || opid == LEFT_ASSIGN
5432                 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
5433               code = FLG_SHIFTSIGNED;
5434             }
5435
5436             if (!ctype_isUnsigned (tr1)) 
5437               {
5438                 if (exprNode_isNonNegative (e1)) {
5439                   ;
5440                 } else {
5441                   reported = optgenerror 
5442                     (code,
5443                      message ("Left operand of %s is not unsigned value (%t): %s",
5444                               lltok_unparse (op), te1,
5445                               exprNode_unparse (ret)),
5446                      e1->loc);
5447                   
5448                   if (reported) {
5449                     te1 = ctype_uint;
5450                   }
5451                 }
5452               }
5453             else 
5454               {
5455                 /* right need not be signed for shifts */
5456                 if (code != FLG_SHIFTSIGNED 
5457                     && !ctype_isUnsigned (tr2)) 
5458                   {
5459                     if (!exprNode_isNonNegative (e2)) {
5460                       reported = optgenerror 
5461                         (code,
5462                          message ("Right operand of %s is not unsigned value (%t): %s",
5463                                   lltok_unparse (op), te2,
5464                                   exprNode_unparse (ret)),
5465                          e2->loc);
5466                     }
5467                   }
5468               }
5469             
5470             if (!reported) 
5471               {
5472                 if (!checkIntegral (e1, e2, ret, op)) {
5473                   te1 = ctype_unknown;
5474                 }
5475               }
5476             
5477             DPRINTF (("Set: %s", ctype_unparse (te1)));     
5478
5479             /*
5480             ** tret is the widest type of te1 and te2 
5481             */
5482
5483             tret = ctype_widest (te1, te2);
5484             break;
5485           }
5486         case MOD_ASSIGN:
5487         case TPERCENT:          
5488           if (checkIntegral (e1, e2, ret, op)) {
5489             tret = te1;
5490           } else {
5491             tret = ctype_unknown;
5492           }
5493           break;
5494         case EQ_OP: 
5495         case NE_OP:
5496         case TLT:               /* comparisons                           */
5497         case TGT:               /*    numeric, numeric -> bool           */
5498           if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5499               || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5500             {
5501               ctype rtype = tr1;
5502               bool fepsilon = FALSE;
5503
5504               if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5505                 {
5506                   rtype = tr2;
5507                 }
5508               
5509               if (opid == TLT || opid == TGT)
5510                 {
5511                   uentry ue1 = exprNode_getUentry (e1);
5512                   uentry ue2 = exprNode_getUentry (e2);
5513
5514                   /*
5515                   ** FLT_EPSILON, etc. really is a variable, not
5516                   ** a constant.
5517                   */
5518
5519                   if (uentry_isVariable (ue1))
5520                     {
5521                       cstring uname = uentry_rawName (ue1);
5522
5523                       if (cstring_equalLit (uname, "FLT_EPSILON")
5524                           || cstring_equalLit (uname, "DBL_EPSILON")
5525                           || cstring_equalLit (uname, "LDBL_EPSILON"))
5526                         {
5527                           fepsilon = TRUE;
5528                         }
5529                     }
5530
5531                   if (uentry_isVariable (ue2))
5532                     {
5533                       cstring uname = uentry_rawName (ue2);
5534
5535                       if (cstring_equalLit (uname, "FLT_EPSILON")
5536                           || cstring_equalLit (uname, "DBL_EPSILON")
5537                           || cstring_equalLit (uname, "LDBL_EPSILON"))
5538                         {
5539                           fepsilon = TRUE;
5540                         }
5541                     }
5542                 }
5543
5544               if (fepsilon)
5545                 {
5546                   ; /* Don't complain. */
5547                 }
5548               else
5549                 {
5550                   voptgenerror
5551                     (FLG_REALCOMPARE,
5552                      message ("Dangerous comparison involving %s types: %s",
5553                               ctype_unparse (rtype),
5554                               exprNode_unparse (ret)),
5555                      ret->loc);
5556                 }
5557             }
5558           /*@fallthrough@*/
5559         case LE_OP:
5560         case GE_OP:
5561
5562           /*
5563           ** Types should match.
5564           */
5565
5566           if (!exprNode_matchTypes (e1, e2))
5567             {
5568               hasError = gentypeerror 
5569                 (te1, e1, te2, e2,
5570                  message ("Operands of %s have incompatible types (%t, %t): %s",
5571                           lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5572                  e1->loc);
5573               
5574             }
5575
5576           if (hasError 
5577               || (ctype_isForceRealNumeric (&tr1)
5578                   && ctype_isForceRealNumeric (&tr2)) ||
5579               (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5580             {
5581               ; /* okay */
5582             }
5583           else
5584             {
5585               if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5586                   (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5587                 {
5588                   voptgenerror 
5589                     (FLG_PTRNUMCOMPARE,
5590                      message ("Comparison of pointer and numeric (%t, %t): %s",
5591                               te1, te2, exprNode_unparse (ret)),
5592                      e1->loc);
5593                 }
5594               else
5595                 {
5596                   (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5597                 }
5598               tret = ctype_bool;
5599             }
5600
5601           /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5602           
5603           if ((opid == EQ_OP || opid == NE_OP) && 
5604               ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5605             {
5606               /*
5607               ** is one a variable?
5608               */
5609
5610               if (uentry_isVariable (exprNode_getUentry (e1))
5611                   || uentry_isVariable (exprNode_getUentry (e2)))
5612                 {
5613                   /*
5614                   ** comparisons with FALSE are okay
5615                   */
5616
5617                   if (exprNode_isFalseConstant (e1)
5618                       || exprNode_isFalseConstant (e2))
5619                     {
5620                       ;
5621                     }
5622                   else
5623                     {
5624                       voptgenerror
5625                         (FLG_BOOLCOMPARE,
5626                          message 
5627                          ("Use of %q with %s variables (risks inconsistency because "
5628                           "of multiple true values): %s",
5629                           cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5630                           context_printBoolName (), exprNode_unparse (ret)),
5631                          e1->loc);
5632                     }
5633                 }
5634             }
5635           break;
5636           
5637         case AND_OP:            /* bool, bool -> bool */
5638         case OR_OP:
5639
5640           if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5641             {
5642               ; 
5643             }
5644           else
5645             {
5646               if (context_maybeSet (FLG_BOOLOPS))
5647                 {
5648                   if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5649                     {
5650                       if (ctype_sameName (te1, te2))
5651                         {
5652                           voptgenerror 
5653                             (FLG_BOOLOPS,
5654                              message ("Operands of %s are non-boolean (%t): %s",
5655                                       lltok_unparse (op), te1,
5656                                       exprNode_unparse (ret)),
5657                              e1->loc);
5658                         }
5659                       else
5660                         {
5661                           voptgenerror 
5662                             (FLG_BOOLOPS,
5663                              message
5664                              ("Operands of %s are non-booleans (%t, %t): %s",
5665                               lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5666                              e1->loc);
5667                         }
5668                     }
5669                   else if (!ctype_isRealBool (te1))
5670                     {
5671                       voptgenerror 
5672                         (FLG_BOOLOPS,
5673                          message ("Left operand of %s is non-boolean (%t): %s",
5674                                   lltok_unparse (op), te1, exprNode_unparse (ret)),
5675                          e1->loc);
5676                     }
5677                   else if (!ctype_isRealBool (te2))
5678                     {
5679                       voptgenerror
5680                         (FLG_BOOLOPS,
5681                          message ("Right operand of %s is non-boolean (%t): %s",
5682                                   lltok_unparse (op), te2, exprNode_unparse (ret)),
5683                          e2->loc);
5684                     }
5685                   else
5686                     {
5687                       ;
5688                     }
5689                 }
5690               tret = ctype_bool;
5691             }
5692           break;
5693         default: {
5694             llfatalbug 
5695               (cstring_makeLiteral 
5696                ("There has been a problem in the parser. This is believed to result "
5697                 "from a problem with bison v. 1.25.  Please try rebuidling LCLint "
5698                 "using the pre-compiled grammar files by commenting out the "
5699                 "BISON= line in the top-level Makefile."));
5700           }
5701         }
5702     }
5703
5704   DPRINTF (("Return type: %s", ctype_unparse (tret)));
5705   ret->typ = tret;
5706
5707   exprNode_checkUse (ret, e1->sref, e1->loc);  
5708   exprNode_mergeUSs (ret, e2);
5709   exprNode_checkUse (ret, e2->sref, e2->loc);  
5710
5711   return ret;
5712 }
5713
5714 /*@only@*/ exprNode
5715 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5716              /*@only@*/ lltok op)
5717 {
5718   exprNode ret;
5719
5720   checkMacroParen (e1);
5721   checkMacroParen (e2);
5722
5723   if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5724     {
5725       checkExpressionDefined (e1, e2, op);
5726     }
5727
5728   ret = exprNode_makeOp (e1, e2, op);
5729   return (ret);
5730 }
5731
5732 static
5733 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5734 {
5735   /*
5736   ** This is somewhat bogus!
5737   **
5738   ** Assigning to a nested observer in a non-observer datatype
5739   ** should not produce an error.
5740   */
5741
5742   sRef ref = exprNode_getSref (e1);
5743
5744   DPRINTF (("Check assign mod: %s",
5745             sRef_unparseFull (ref)));
5746
5747   if (sRef_isObserver (ref) 
5748       || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5749           && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5750     {
5751       sRef base = sRef_getBase (ref);
5752
5753       if (sRef_isValid (base) && sRef_isObserver (base))
5754         {
5755           exprNode_checkModify (e1, ret);
5756         }
5757       else
5758         {
5759           exprNode_checkModifyVal (e1, ret);
5760         }
5761     }
5762   else
5763     {
5764       exprNode_checkModify (e1, ret);
5765     }
5766 }
5767
5768 exprNode
5769 exprNode_assign (/*@only@*/ exprNode e1,
5770                  /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5771 {
5772   bool isalloc = FALSE;
5773   bool isjustalloc = FALSE;
5774   exprNode ret;
5775
5776   DPRINTF (("%s [%s] <- %s [%s]",
5777             exprNode_unparse (e1),
5778             ctype_unparse (e1->typ),
5779             exprNode_unparse (e2),
5780             ctype_unparse (e2->typ)));
5781
5782   if (lltok_getTok (op) != TASSIGN) 
5783     {
5784       ret = exprNode_makeOp (e1, e2, op);
5785     } 
5786   else 
5787     {
5788       ret = exprNode_createPartialCopy (e1);
5789       ret->kind = XPR_ASSIGN;
5790       ret->edata = exprData_makeOp (e1, e2, op);
5791
5792       if (!exprNode_isError (e2)) 
5793         {
5794           ret->sets = sRefSet_union (ret->sets, e2->sets);
5795           ret->msets = sRefSet_union (ret->msets, e2->msets);
5796           ret->uses = sRefSet_union (ret->uses, e2->uses);
5797         }
5798     }
5799
5800   checkExpressionDefined (e1, e2, op);
5801
5802   if (exprNode_isError (e1))
5803     {
5804       if (!exprNode_isError (e2)) 
5805         {
5806           ret->loc = fileloc_update (ret->loc, e2->loc);
5807         }
5808       else
5809         {
5810           ret->loc = fileloc_update (ret->loc, g_currentloc);
5811         }
5812     }
5813
5814   if (!exprNode_isError (e2))
5815     {
5816       checkMacroParen (e2);
5817     }
5818
5819   if (exprNode_isDefined (e1))
5820     {
5821       if (sRef_isMacroParamRef (e1->sref))
5822         {
5823           if (context_inIterDef ())
5824             {
5825               uentry ue = sRef_getUentry (e1->sref);
5826               
5827               if (uentry_isYield (ue))
5828                 {
5829                   ;
5830                 }
5831               else
5832                 {
5833                   if (fileloc_isDefined (e1->loc))
5834                     {
5835                       voptgenerror
5836                         (FLG_MACROPARAMS,
5837                          message ("Assignment to non-yield iter parameter: %q", 
5838                                   sRef_unparse (e1->sref)),
5839                          e1->loc);
5840                     }
5841                   else
5842                     {
5843                       voptgenerror 
5844                         (FLG_MACROPARAMS,
5845                          message ("Assignment to non-yield iter parameter: %q", 
5846                                   sRef_unparse (e1->sref)),
5847                          g_currentloc);
5848                     }
5849                 }
5850             }
5851           else
5852             {
5853               if (fileloc_isDefined (e1->loc))
5854                 {
5855                   voptgenerror
5856                     (FLG_MACROASSIGN,
5857                      message ("Assignment to macro parameter: %q", 
5858                               sRef_unparse (e1->sref)),
5859                      e1->loc);
5860                 }
5861               else
5862                 {
5863                   voptgenerror 
5864                     (FLG_MACROASSIGN,
5865                      message ("Assignment to macro parameter: %q", 
5866                               sRef_unparse (e1->sref)),
5867                      g_currentloc);
5868                 }
5869
5870               exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
5871             }
5872         }
5873       else
5874         {
5875           exprNode_checkAssignMod (e1, ret);
5876         }
5877
5878       if (exprNode_isDefined (e2))
5879         {
5880           if (lltok_getTok (op) == TASSIGN) 
5881             {
5882               ctype te1 = exprNode_getType (e1);
5883               ctype te2 = exprNode_getType (e2);
5884               
5885               if (!ctype_forceMatch (te1, te2))
5886                 {
5887                   if (exprNode_matchLiteral (te1, e2))
5888                     {
5889                       ;
5890                     }
5891                   else
5892                     {
5893                       (void) gentypeerror 
5894                         (te2, e2, te1, e1,
5895                          message ("Assignment of %t to %t: %s %s %s", 
5896                                   te2, te1, exprNode_unparse (e1),
5897                                   lltok_unparse (op), 
5898                                   exprNode_unparse (e2)),
5899                          e1->loc);
5900                     }
5901                 }
5902             }
5903          
5904           exprNode_mergeUSs (ret, e2);
5905           exprNode_checkUse (ret, e2->sref, e2->loc);
5906           
5907           doAssign (e1, e2, FALSE); 
5908           ret->sref = e1->sref;
5909         }
5910       else
5911         {
5912           if (exprNode_isDefined (e2))
5913             {
5914               exprNode_mergeUSs (ret, e2);
5915                       exprNode_checkUse (ret, e2->sref, e2->loc);
5916             }
5917         }
5918
5919       if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
5920         {
5921           exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
5922         }
5923
5924       isjustalloc = sRef_isJustAllocated (e1->sref);
5925       isalloc = sRef_isAllocated (e1->sref);
5926
5927       if (sRef_isField (e1->sref))
5928         {
5929           sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
5930           
5931           if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
5932             {
5933               exprNode_checkUse (ret, root, e1->loc);
5934             }
5935           
5936         }
5937   
5938       /*
5939       ** be careful!  this defines e1->sref.
5940       */
5941
5942       /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
5943
5944       exprNode_checkSet (ret, e1->sref);
5945       
5946       if (isjustalloc) 
5947         {
5948           sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
5949                                      ? e2->loc : e1->loc);
5950         }
5951       else 
5952         {
5953           if (isalloc)
5954             {
5955               sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
5956             }
5957         }
5958     }
5959   
5960   return ret;
5961 }
5962
5963 exprNode
5964 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause, 
5965                /*@keep@*/ exprNode elseclause)
5966 {
5967   exprNode ret;
5968
5969   if (!exprNode_isError (pred))
5970     {
5971       ret = exprNode_createPartialCopy (pred);
5972       checkMacroParen (pred);
5973       exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
5974       
5975       if (!exprNode_isError (ifclause))
5976         {
5977           checkMacroParen (ifclause);   /* update macro counts! */
5978
5979           if (!exprNode_isError (elseclause))
5980             {
5981               checkMacroParen (elseclause);
5982               
5983               if (!exprNode_matchTypes (ifclause, elseclause))
5984                 {
5985                   if (gentypeerror 
5986                       (exprNode_getType (ifclause),
5987                        ifclause,
5988                        exprNode_getType (elseclause),
5989                        elseclause,
5990                        message ("Conditional clauses are not of same type: "
5991                                 "%s (%t), %s (%t)", 
5992                                 exprNode_unparse (ifclause), 
5993                                 exprNode_getType (ifclause),
5994                                 exprNode_unparse (elseclause), 
5995                                 exprNode_getType (elseclause)),
5996                        ifclause->loc))
5997                     {
5998                       ret->sref = sRef_undefined;
5999                       ret->typ = ctype_unknown;
6000                     }
6001                 }
6002               else
6003                 {
6004                   /* for now...should merge the states */
6005                   ret->sref = ifclause->sref;
6006                   ret->typ = ifclause->typ;
6007
6008                   if (exprNode_isNullValue (ifclause))
6009                     {
6010                       ret->typ = elseclause->typ;
6011                     }
6012                 }
6013               
6014               exprNode_checkUse (ret, pred->sref, pred->loc);
6015               exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6016               exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6017
6018               exprNode_mergeCondUSs (ret, ifclause, elseclause);
6019
6020             }
6021           else
6022             {
6023               ret->typ = ifclause->typ;
6024               
6025               exprNode_checkUse (pred, pred->sref, pred->loc);
6026               exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6027               
6028               exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6029             }
6030         }
6031       else 
6032         {
6033           if (!exprNode_isError (elseclause))
6034             {
6035               ret->typ = elseclause->typ;
6036               
6037               exprNode_checkUse (pred, pred->sref, pred->loc);
6038               exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6039               
6040               exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6041             }
6042         }
6043     }
6044   else /* pred is error */
6045     {
6046       if (!exprNode_isError (ifclause))
6047         {
6048           ret = exprNode_createSemiCopy (ifclause);
6049
6050           checkMacroParen (ifclause);   /* update macro counts! */
6051           
6052           if (!exprNode_isError (elseclause))
6053             {
6054               checkMacroParen (elseclause);
6055               
6056               ret->typ = ifclause->typ;
6057                       
6058               if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6059                 {
6060                   if (gentypeerror 
6061                       (exprNode_getType (ifclause),
6062                        ifclause,
6063                        exprNode_getType (elseclause),
6064                        elseclause,
6065                        message ("Conditional clauses are not of same type: "
6066                                 "%s (%t), %s (%t)", 
6067                                 exprNode_unparse (ifclause), 
6068                                 exprNode_getType (ifclause),
6069                                 exprNode_unparse (elseclause), 
6070                                 exprNode_getType (elseclause)),
6071                        ifclause->loc))
6072                     {
6073                       ret->typ = ctype_unknown;
6074                     }
6075                 }
6076                       
6077               exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6078               exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6079               
6080               exprNode_mergeCondUSs (ret, ifclause, elseclause);
6081             }
6082         }
6083       else if (!exprNode_isError (elseclause)) /* pred, if errors */
6084         {
6085           ret = exprNode_createSemiCopy (ifclause);
6086
6087           ret->typ = elseclause->typ;
6088           checkMacroParen (elseclause);
6089           
6090           exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6091           exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6092         }
6093       else /* all errors! */
6094         {
6095           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6096         }
6097     }
6098   
6099   ret->kind = XPR_COND;
6100   ret->edata = exprData_makeCond (pred, ifclause, elseclause);  
6101
6102   if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6103     {
6104       exprNode_combineControl (ret, ifclause, elseclause);
6105     }
6106
6107   return (ret);
6108 }
6109
6110 exprNode
6111 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6112 {
6113   ctype totype = qtype_getType (qt);
6114   exprNode ret =
6115     exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6116   ctype targ;
6117
6118   /*
6119   ** check use of va_arg : <valist>, type -> type
6120   */
6121
6122   if (exprNode_isError (arg))
6123     {
6124     }
6125   else
6126     {
6127       targ = exprNode_getType (arg);
6128
6129       /*
6130       ** arg should have be a pointer
6131       */
6132
6133       if (!ctype_isUA (targ) ||
6134           (!usymId_equal (ctype_typeId (targ), 
6135                          usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6136         {
6137           voptgenerror
6138             (FLG_TYPE,
6139              message ("First argument to va_arg is not a va_list (type %t): %s",
6140                       targ, exprNode_unparse (arg)),
6141              arg->loc);
6142         }
6143
6144       exprNode_checkSet (ret, arg->sref);
6145     }
6146   
6147   /*
6148   ** return type is totype
6149   */
6150
6151   ret->typ = totype;
6152   ret->kind = XPR_VAARG;
6153   ret->edata = exprData_makeCast (tok, arg, qt);
6154
6155   return (ret);
6156 }
6157
6158 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6159 {
6160   exprNode ret = exprNode_createPlain (ctype_undefined);
6161   ret->kind = XPR_LABEL;
6162   ret->edata = exprData_makeLiteral (label);
6163   ret->isJumpPoint = TRUE;
6164
6165   return (ret); /* for now, ignore label */
6166 }
6167
6168 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6169 {
6170   if (exprNode_isDefined (stmt))
6171     {
6172       stmt->isJumpPoint = TRUE;
6173
6174       /* This prevent stray no return path errors, etc. */
6175       stmt->exitCode = XK_MUSTEXIT;
6176     }
6177
6178   return (stmt); 
6179 }
6180
6181 bool exprNode_isDefaultMarker (exprNode e) 
6182 {
6183   if (exprNode_isDefined (e))
6184     {
6185       return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6186     }
6187
6188   return FALSE;
6189 }
6190
6191 bool exprNode_isCaseMarker (exprNode e) 
6192 {
6193   if (exprNode_isDefined (e))
6194     {
6195       return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6196     }
6197
6198   return FALSE;
6199 }
6200
6201 bool exprNode_isLabelMarker (exprNode e) 
6202 {
6203   if (exprNode_isDefined (e))
6204     {
6205       return (e->kind == XPR_LABEL);
6206     }
6207
6208   return FALSE;
6209 }
6210
6211 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough) 
6212 {
6213   exprNode ret = exprNode_createPartialCopy (test);
6214
6215   ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6216
6217   if (exprNode_isError (test)) {
6218     return ret;
6219   }
6220
6221   exprNode_checkUse (ret, test->sref, test->loc);
6222   
6223   usymtab_setExitCode (ret->exitCode);
6224   
6225   if (ret->mustBreak)
6226     {
6227       usymtab_setMustBreak ();
6228     }
6229
6230   ret->edata = exprData_makeSingle (test);
6231   ret->isJumpPoint = TRUE;
6232   
6233   return ret;
6234 }
6235
6236 # if 0
6237 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6238 {
6239   exprNode ret = exprNode_createPartialCopy (test);
6240
6241   ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6242   ret->edata = exprData_makePair (test, stmt);
6243   ret->isJumpPoint = TRUE;
6244
6245   if (exprNode_isError (test))
6246     {
6247       return ret;
6248     }
6249
6250   exprNode_checkUse (ret, test->sref, test->loc);
6251   
6252   if (exprNode_isError (stmt))
6253     {
6254       return ret;
6255     }
6256   
6257   exprNode_mergeUSs (ret, stmt);
6258   
6259   ret->exitCode = stmt->exitCode;
6260   ret->mustBreak = stmt->mustBreak;
6261   ret->canBreak = stmt->canBreak;
6262
6263   usymtab_setExitCode (ret->exitCode);
6264   
6265   if (ret->mustBreak)
6266     {
6267       usymtab_setMustBreak ();
6268     }
6269   
6270   return ret;
6271 }
6272 # endif
6273
6274 /*@notnull@*/ /*@only@*/ exprNode 
6275 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6276 {
6277   exprNode ret = exprNode_createTok (def);
6278   
6279   ret->isJumpPoint = TRUE;
6280   ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6281   return (ret);
6282 }
6283
6284 bool
6285 exprNode_mayEscape (exprNode e)
6286 {
6287   if (exprNode_isDefined (e))
6288     {
6289       return exitkind_couldEscape (e->exitCode);
6290     }
6291   return FALSE;
6292 }
6293
6294 static bool
6295 exprNode_mustBreak (exprNode e)
6296 {
6297   if (exprNode_isDefined (e))
6298     {
6299       return e->mustBreak;
6300     }
6301   return FALSE;
6302 }
6303
6304 bool
6305 exprNode_mustEscape (exprNode e)
6306 {
6307   if (exprNode_isDefined (e))
6308     {
6309       return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6310     }
6311
6312   return FALSE;
6313 }
6314
6315 bool
6316 exprNode_errorEscape (exprNode e)
6317 {
6318   if (exprNode_isDefined (e))
6319     {
6320       return exitkind_isError (e->exitCode);
6321     }
6322
6323   return FALSE;
6324 }
6325
6326 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6327 {
6328   exprNode ret = exprNode_createPartialCopy (e1);
6329
6330   DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6331
6332   ret->edata = exprData_makePair (e1, e2);
6333   ret->kind = XPR_STMTLIST;
6334
6335   if (exprNode_isDefined (e1))
6336     {
6337       ret->isJumpPoint = e1->isJumpPoint;
6338       ret->canBreak = e1->canBreak;
6339     }
6340   else
6341     {
6342       if (exprNode_isDefined (e2))
6343         {
6344           ret->loc = fileloc_update (ret->loc, e2->loc);
6345         }
6346     }
6347
6348   if (exprNode_isDefined (e2))
6349     {
6350       ret->exitCode = e2->exitCode;
6351       ret->mustBreak = e2->mustBreak;
6352       if (e2->canBreak) ret->canBreak = TRUE;
6353     }
6354
6355   /* 
6356   ** if e1 must return, then e2 is unreachable!
6357   */
6358
6359   if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6360     {
6361       if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1)) 
6362           && !(e2->isJumpPoint))
6363         {
6364           if (context_getFlag (FLG_UNREACHABLE))
6365             {
6366               exprNode nr = e2;
6367
6368               if (e2->kind == XPR_STMT)
6369                 {
6370                   nr = exprData_getUopNode (e2->edata);
6371                 }
6372
6373               if ((nr->kind == XPR_TOK 
6374                    && lltok_isSemi (exprData_getTok (nr->edata))))
6375                 {
6376                   /* okay to have unreachable ";" */
6377                   ret->exitCode = XK_MUSTEXIT;
6378                   ret->canBreak = TRUE;
6379                 }
6380               else
6381                 {
6382                   if (optgenerror (FLG_UNREACHABLE,
6383                                    message ("Unreachable code: %s", 
6384                                             exprNode_unparseFirst (nr)),
6385                                    exprNode_loc (nr)))
6386                     {
6387                       ret->isJumpPoint = TRUE;                
6388                       ret->mustBreak = FALSE;
6389                       ret->exitCode = XK_ERROR;
6390                       DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6391                     }
6392                   else
6393                     {
6394                       ret->exitCode = XK_MUSTEXIT;
6395                       ret->canBreak = TRUE;
6396                     }
6397
6398                 }
6399             }
6400         }
6401       else
6402         {
6403           if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6404             {
6405               /*
6406               ** We want a warning anytime we have:
6407               **         case xxx: ...  
6408               **                   yyy;  <<<- no break or return
6409               **         case zzz: ...
6410               */
6411               
6412               exprNode lastStmt = exprNode_lastStatement (e1);
6413               
6414               if (exprNode_isDefined (lastStmt) 
6415                   && !exprNode_mustEscape (lastStmt)
6416                   && !exprNode_mustBreak (lastStmt)
6417                   && !exprNode_isCaseMarker (lastStmt)
6418                   && !exprNode_isDefaultMarker (lastStmt)
6419                   && !exprNode_isLabelMarker (lastStmt))
6420                 {
6421                   voptgenerror (FLG_CASEBREAK,
6422                                 cstring_makeLiteral 
6423                                 ("Fall through case (no preceeding break)"),
6424                                 e2->loc);
6425                 }
6426             }
6427         }
6428     }
6429
6430   exprNode_mergeUSs (ret, e2);
6431   
6432   usymtab_setExitCode (ret->exitCode);
6433   
6434   if (ret->mustBreak)
6435     {
6436       usymtab_setMustBreak ();
6437     }
6438
6439   return ret;
6440 }
6441
6442 exprNode exprNode_createTok (/*@only@*/ lltok t)
6443 {
6444   exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6445   ret = exprNode_create (ctype_unknown);
6446   ret->kind = XPR_TOK;
6447   ret->edata = exprData_makeTok (t);
6448   return ret;
6449 }
6450
6451 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6452 {
6453   if (!exprNode_isError (e))
6454     {
6455       exprNode_checkStatement(e);
6456     }
6457
6458   return (exprNode_statementError (e, t));
6459 }
6460
6461 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6462 {
6463   exprNode ret = exprNode_createPartialCopy (e);
6464
6465   if (!exprNode_isError (e))
6466     {
6467       if (e->kind != XPR_ASSIGN)
6468         {
6469           exprNode_checkUse (ret, e->sref, e->loc);
6470         }
6471
6472       ret->exitCode = e->exitCode;
6473       ret->canBreak = e->canBreak;
6474       ret->mustBreak = e->mustBreak;
6475     }
6476   
6477   ret->edata = exprData_makeUop (e, t);
6478   ret->kind = XPR_STMT;
6479
6480   return ret;
6481 }
6482
6483 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6484 {
6485   if (!exprNode_isError (e))
6486     {
6487       if (e->kind != XPR_ASSIGN)
6488         {
6489           exprNode_checkUse (e, e->sref, e->loc);
6490         }
6491     }
6492
6493   return e;
6494 }
6495
6496 void exprNode_produceGuards (exprNode pred)
6497 {
6498   if (!exprNode_isError (pred))
6499     {
6500       if (ctype_isRealPointer (pred->typ))
6501         {
6502           pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6503         }
6504       
6505       exprNode_checkUse (pred, pred->sref, pred->loc);
6506       exprNode_resetSref (pred);
6507     }
6508 }
6509
6510 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6511 {
6512   exprNode ret = exprNode_createPartialCopy (e);
6513
6514   if (!exprNode_isError (e))
6515     {
6516       ret->exitCode = e->exitCode;
6517       ret->canBreak = e->canBreak;
6518       ret->mustBreak = e->mustBreak;
6519     }
6520   
6521   ret->edata = exprData_makeSingle (e);
6522   ret->kind = XPR_BLOCK;
6523   return ret;
6524 }
6525
6526 bool exprNode_isBlock (exprNode e)
6527 {
6528   return (exprNode_isDefined (e) 
6529           && ((e)->kind == XPR_BLOCK));
6530 }
6531  
6532 bool exprNode_isAssign (exprNode e)
6533 {
6534   if (exprNode_isDefined (e))
6535     {
6536       return (e->kind == XPR_ASSIGN);
6537     }
6538
6539   return FALSE;
6540 }
6541
6542 bool exprNode_isEmptyStatement (exprNode e)
6543 {
6544   return (exprNode_isDefined (e) 
6545           && (e->kind == XPR_TOK)
6546           && (lltok_isSemi (exprData_getTok (e->edata))));
6547 }
6548
6549 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6550 {
6551   exprNode ret;
6552   bool emptyErr = FALSE;
6553
6554   if (context_maybeSet (FLG_IFEMPTY))
6555     {
6556       if (exprNode_isEmptyStatement (tclause))
6557         {
6558           emptyErr = optgenerror (FLG_IFEMPTY,
6559                                   cstring_makeLiteral
6560                                   ("Body of if statement is empty"),
6561                                   exprNode_loc (tclause));
6562         }
6563     }
6564
6565   if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6566     {
6567       if (exprNode_isDefined (tclause)
6568           && !exprNode_isBlock (tclause))
6569         {
6570           voptgenerror (FLG_IFBLOCK,
6571                         message
6572                         ("Body of if statement is not a block: %s",
6573                          exprNode_unparse (tclause)),
6574                         exprNode_loc (tclause));
6575         }
6576     }
6577
6578   if (exprNode_isError (pred))
6579     {
6580       if (exprNode_isError (tclause))
6581         {
6582           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6583         }
6584       else
6585         {
6586           ret = exprNode_createPartialCopy (tclause);
6587         }
6588     }
6589   else
6590     {
6591       if (exprNode_mustEscape (pred))
6592         {
6593           voptgenerror 
6594             (FLG_UNREACHABLE,
6595              message ("Predicate always exits: %s", exprNode_unparse (pred)),
6596              exprNode_loc (pred));
6597         }
6598
6599       exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6600       exprNode_checkUse (pred, pred->sref, pred->loc);
6601       
6602       if (!exprNode_isError (tclause))
6603         {
6604           exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6605         }
6606       
6607       ret = exprNode_createPartialCopy (pred);
6608     }
6609
6610   ret->kind = XPR_IF;
6611   ret->edata = exprData_makePair (pred, tclause);
6612
6613   ret->exitCode = XK_UNKNOWN;
6614
6615   if (exprNode_isDefined (tclause))
6616     {
6617       ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6618       ret->canBreak = tclause->canBreak;
6619       ret->sets = sRefSet_union (ret->sets, tclause->sets);
6620       ret->msets = sRefSet_union (ret->msets, tclause->msets);
6621       ret->uses = sRefSet_union (ret->uses, tclause->uses);
6622     }
6623
6624   ret->mustBreak = FALSE;
6625
6626   return ret;
6627 }
6628
6629 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6630                           /*@only@*/ exprNode tclause, 
6631                           /*@only@*/ exprNode eclause)
6632 {
6633   exprNode ret;
6634   bool tEmptyErr = FALSE;
6635   bool eEmptyErr = FALSE;
6636
6637   if (context_maybeSet (FLG_IFEMPTY))
6638     {
6639       if (exprNode_isEmptyStatement (tclause))
6640         {
6641           tEmptyErr = optgenerror 
6642             (FLG_IFEMPTY,
6643              cstring_makeLiteral
6644              ("Body of if clause of if statement is empty"),
6645              exprNode_loc (tclause));
6646         }
6647
6648       if (exprNode_isEmptyStatement (eclause))
6649         {
6650           eEmptyErr = optgenerror 
6651             (FLG_IFEMPTY,
6652              cstring_makeLiteral
6653              ("Body of else clause of if statement is empty"),
6654              exprNode_loc (eclause));
6655         }
6656     }
6657
6658   if (context_maybeSet (FLG_IFBLOCK))
6659     {
6660       if (!tEmptyErr
6661           && exprNode_isDefined (tclause)
6662           && !exprNode_isBlock (tclause))
6663         {
6664           voptgenerror (FLG_IFBLOCK,
6665                         message
6666                         ("Body of if clause of if statement is not a block: %s",
6667                          exprNode_unparse (tclause)),
6668                         exprNode_loc (tclause));
6669         }
6670
6671       if (!eEmptyErr
6672           && exprNode_isDefined (eclause)
6673           && !exprNode_isBlock (eclause)
6674           && !(eclause->kind == XPR_IF)
6675           && !(eclause->kind == XPR_IFELSE))
6676         {
6677           voptgenerror
6678             (FLG_IFBLOCK,
6679              message
6680              ("Body of else clause of if statement is not a block: %s",
6681               exprNode_unparse (eclause)),
6682              exprNode_loc (eclause));
6683         }
6684     }
6685
6686   if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6687     {
6688       if (exprNode_isDefined (eclause)
6689           && (eclause->kind == XPR_IF))
6690         {
6691           voptgenerror (FLG_ELSEIFCOMPLETE,
6692                         message ("Incomplete else if logic (no final else): %s",
6693                                  exprNode_unparse (eclause)),
6694                         exprNode_loc (eclause));
6695         }
6696     }
6697
6698   if (exprNode_isError (pred))
6699     {
6700       if (exprNode_isError (tclause))
6701         {
6702           if (exprNode_isError (eclause))
6703             {
6704               ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6705             }
6706           else
6707             {
6708               ret = exprNode_createPartialCopy (eclause);
6709             }
6710         }
6711       else 
6712         {
6713           ret = exprNode_createPartialCopy (tclause);
6714         }
6715     }
6716   else /* pred is okay */
6717     {
6718       ret = exprNode_createPartialCopy (pred);
6719
6720       if (exprNode_mustEscape (pred))
6721         {
6722           voptgenerror
6723             (FLG_UNREACHABLE,
6724              message ("Predicate always exits: %s", exprNode_unparse (pred)),
6725              exprNode_loc (pred));
6726         }
6727       
6728       exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6729       exprNode_checkUse (ret, pred->sref, pred->loc);
6730       
6731       exprNode_mergeCondUSs (ret, tclause, eclause);
6732     }
6733
6734   ret->kind = XPR_IFELSE;
6735   ret->edata = exprData_makeCond (pred, tclause, eclause);
6736
6737   if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6738     {
6739       exprNode_combineControl (ret, tclause, eclause);
6740       ret->loc = fileloc_update (ret->loc, eclause->loc);
6741     }
6742
6743   return ret;
6744 }
6745
6746 /*
6747 ** *allpaths <- TRUE iff all executions paths must go through the switch
6748 */
6749
6750 static bool
6751 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6752 {
6753   exprNodeSList el = exprNode_flatten (e);
6754   bool mustReturn = TRUE; /* find a branch that doesn't */
6755   bool thisReturn = FALSE;
6756   bool hasDefault = FALSE;
6757   bool hasAllMembers = FALSE;
6758   bool inSwitch = FALSE;
6759   bool isEnumSwitch = FALSE;
6760   bool canBreak = FALSE;
6761   bool fallThrough = FALSE;
6762   ctype ct = ctype_unknown;
6763   enumNameSList usedEnums;
6764   enumNameList enums;
6765
6766   if (exprNode_isDefined (test))
6767     {
6768       ctype ttype;
6769
6770       ct = test->typ;
6771       ttype = ctype_realType (ct);
6772
6773       if (ctype_isEnum (ttype))
6774         {
6775           isEnumSwitch = TRUE;
6776           enums = ctype_elist (ttype);
6777           usedEnums = enumNameSList_new ();
6778         }
6779     }
6780
6781   exprNodeSList_elements (el, current)
6782     {
6783       if (exprNode_isDefined (current))
6784         {
6785           switch (current->kind)
6786             {
6787             case XPR_FTDEFAULT:
6788             case XPR_DEFAULT:
6789               if (hasDefault)
6790                 {
6791                   voptgenerror 
6792                     (FLG_CONTROL,
6793                      message ("Duplicate default cases in switch"),
6794                      exprNode_loc (current));
6795                 }          
6796             /*@fallthrough@*/
6797             case XPR_FTCASE:
6798             case XPR_CASE: 
6799               if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6800                 {
6801                   hasDefault = TRUE; 
6802                 }
6803               else
6804                 {
6805                   if (isEnumSwitch)
6806                     {
6807                       exprNode st = exprData_getSingle (current->edata);
6808                       uentry ue = exprNode_getUentry (st);
6809                       
6810                       if (uentry_isValid (ue))
6811                         {
6812                           cstring cname = uentry_rawName (ue);
6813                           
6814                           if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6815                             {
6816                               if (enumNameSList_member
6817                                   (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6818                                 {
6819                                   voptgenerror
6820                                     (FLG_CONTROL,
6821                                      message ("Duplicate case in switch: %s", 
6822                                               cname),
6823                                      current->loc);
6824                                 }
6825                               else
6826                                 {
6827                                   enumNameSList_addh (usedEnums, cname);
6828                                 }
6829                             }
6830                           else
6831                             {
6832                               voptgenerror 
6833                                 (FLG_TYPE,
6834                                  message ("Case in switch not %s member: %s", 
6835                                           ctype_unparse (ct), cname),
6836                                  current->loc);
6837                             }
6838                         }
6839                     }
6840                 }
6841               
6842               if (inSwitch && !fallThrough)
6843                 {
6844                   if (!thisReturn || canBreak) 
6845                     {
6846                       mustReturn = FALSE;
6847                     }
6848                 }
6849               
6850               fallThrough = TRUE;
6851               inSwitch = TRUE;
6852               thisReturn = FALSE;
6853               canBreak = FALSE;
6854               /*@switchbreak@*/ break;
6855             default:
6856               thisReturn = thisReturn || exprNode_mustEscape (current);
6857               canBreak = canBreak || current->canBreak;
6858               if (canBreak) fallThrough = FALSE;
6859             }
6860         }
6861     } end_exprNodeSList_elements;
6862
6863   if (inSwitch) /* check the last one! */
6864     {
6865       if (!thisReturn || canBreak) 
6866         {
6867           mustReturn = FALSE;
6868         }
6869     }
6870   
6871   if (isEnumSwitch)
6872     {
6873       if (!hasDefault 
6874           && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) != 
6875               enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6876         {
6877           enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6878           
6879           voptgenerror (FLG_MISSCASE,
6880                         message ("Missing case%s in switch: %q",
6881                                  cstring_makeLiteralTemp 
6882                                  ((enumNameSList_size (unused) > 1) ? "s" : ""),
6883                                  enumNameSList_unparse (unused)),
6884                         g_currentloc);
6885
6886           enumNameSList_free (unused);
6887         }
6888       else
6889         {
6890           hasAllMembers = TRUE;
6891           *allpaths = TRUE;
6892         }
6893
6894       enumNameSList_free (usedEnums);
6895     }
6896   else
6897     {
6898       *allpaths = hasDefault;
6899     }
6900
6901   exprNodeSList_free (el);
6902   return ((hasDefault || hasAllMembers) && mustReturn);  
6903 }
6904     
6905 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6906 {
6907   exprNode ret = exprNode_createPartialCopy (e);
6908   bool allpaths;
6909
6910   DPRINTF (("Switch: %s", exprNode_unparse (s)));
6911
6912   ret->kind = XPR_SWITCH;
6913   ret->edata = exprData_makePair (e, s);
6914   
6915   if (!exprNode_isError (s))
6916     {
6917       exprNode fs = exprNode_firstStatement (s);
6918       ret->loc = fileloc_update (ret->loc, s->loc);
6919
6920       if (exprNode_isUndefined (fs) 
6921           || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6922           || exprNode_isDefaultMarker (fs)) {
6923         ;
6924       } else {
6925         voptgenerror (FLG_FIRSTCASE,
6926                       message
6927                       ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6928                       fs->loc);
6929       }
6930     }
6931
6932   if (!exprNode_isError (e)) 
6933     {
6934       if (checkSwitchExpr (e, s, &allpaths))
6935         {
6936           ret->exitCode = XK_MUSTRETURN;
6937         }
6938       else
6939         {
6940           ret->exitCode = e->exitCode;
6941         }
6942
6943       ret->canBreak = e->canBreak;
6944       ret->mustBreak = e->mustBreak;
6945     }
6946   /*
6947   ** forgot this!
6948   **   exprNode.c:3883,32: Variable allpaths used before definition
6949   */
6950   else 
6951     {
6952       allpaths = FALSE;
6953     }
6954   
6955   DPRINTF (("Context exit switch!"));
6956   context_exitSwitch (ret, allpaths);
6957   DPRINTF (("Context exit switch done!"));
6958
6959   return ret;
6960 }
6961
6962 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
6963                                /*@notnull@*/ exprNode body)
6964 {
6965   sRefSet tuses = test->uses;
6966   
6967   if (!sRefSet_isEmpty (test->uses))
6968     {
6969       sRefSet sets = sRefSet_newCopy (body->sets);
6970       bool hasError = TRUE;
6971       bool innerState = FALSE;
6972       sRefSet tuncon = sRefSet_undefined;
6973       
6974       sets = sRefSet_union (sets, test->sets);
6975       sets = sRefSet_union (sets, body->msets);
6976       sets = sRefSet_union (sets, test->msets);
6977
6978       sRefSet_allElements (tuses, el)
6979         {
6980           if (sRef_isUnconstrained (el))
6981             {
6982               tuncon = sRefSet_insert (tuncon, el);
6983             }
6984           else
6985             {
6986               if (sRefSet_member (sets, el))
6987                 {
6988                   hasError = FALSE;
6989                   break;
6990                 }
6991             }
6992
6993           if (sRef_isInternalState (el)
6994               || sRef_isFileStatic (sRef_getRootBase (el)))
6995             {
6996               innerState = TRUE;
6997             }
6998         } end_sRefSet_allElements ;
6999
7000       if (hasError)
7001         {
7002           sRefSet suncon = sRefSet_undefined;
7003           bool sinner = FALSE;
7004
7005           sRefSet_allElements (sets, el)
7006             {
7007               if (sRef_isUnconstrained (el))
7008                 {
7009                   suncon = sRefSet_insert (suncon, el);
7010                 }
7011               else if (sRef_isInternalState (el))
7012                 {
7013                   sinner = TRUE;
7014                 }
7015               else
7016                 {
7017                   ;
7018                 }
7019             } end_sRefSet_allElements ;
7020
7021           if (sinner && innerState)
7022             {
7023               ; 
7024             }
7025           else if (sRefSet_isEmpty (tuncon)
7026                    && sRefSet_isEmpty (suncon))
7027             {
7028               voptgenerror 
7029                 (FLG_INFLOOPS,
7030                  message
7031                  ("Suspected infinite loop.  No value used in loop test (%q) "
7032                   "is modified by test or loop body.",
7033                   sRefSet_unparsePlain (tuses)), 
7034                  test->loc);
7035             }
7036           else
7037             {
7038               if (sRefSet_isEmpty (tuncon))
7039                 {
7040                   voptgenerror 
7041                     (FLG_INFLOOPSUNCON,
7042                      message ("Suspected infinite loop.  No condition values "
7043                               "modified.  Modification possible through "
7044                               "unconstrained calls: %q",
7045                               sRefSet_unparsePlain (suncon)), 
7046                      test->loc);
7047                 }
7048               else
7049                 {
7050                   voptgenerror 
7051                     (FLG_INFLOOPSUNCON,
7052                      message ("Suspected infinite loop.  No condition values "
7053                               "modified.  Possible undetected dependency through "
7054                               "unconstrained calls in loop test: %q",
7055                               sRefSet_unparsePlain (tuncon)), 
7056                      test->loc);
7057                 }
7058             }
7059         }
7060
7061       sRefSet_free (sets);
7062     }
7063 }
7064
7065 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7066 {
7067   exprNode ret;
7068   bool emptyErr = FALSE;
7069   
7070   if (context_maybeSet (FLG_WHILEEMPTY))
7071     {
7072       if (exprNode_isEmptyStatement (b))
7073         {
7074           emptyErr = optgenerror 
7075             (FLG_WHILEEMPTY,
7076              cstring_makeLiteral
7077              ("Body of while statement is empty"),
7078              exprNode_loc (b));
7079         }
7080     }
7081
7082   if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7083     {
7084       if (exprNode_isDefined (b)
7085           && !exprNode_isBlock (b))
7086         {
7087           if (context_inIterDef ()
7088               && (b->kind == XPR_STMTLIST
7089                   || b->kind == XPR_TOK))
7090             {
7091               ; /* no error */
7092             }
7093           else
7094             {
7095               voptgenerror (FLG_WHILEBLOCK,
7096                             message
7097                             ("Body of while statement is not a block: %s",
7098                              exprNode_unparse (b)),
7099                             exprNode_loc (b));
7100             }
7101         }
7102     }
7103   
7104   if (exprNode_isError (t))
7105     {
7106       if (exprNode_isError (b))
7107         {
7108           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7109         }
7110       else
7111         {
7112           ret = exprNode_createPartialCopy (b);
7113         }
7114     }
7115   else
7116     {
7117       exprNode test;
7118
7119       ret = exprNode_createPartialCopy (t);
7120       
7121       llassert (t->kind == XPR_WHILEPRED);
7122
7123       test = exprData_getSingle (t->edata);
7124
7125       if (!exprNode_isError (b) && exprNode_isDefined (test))
7126         {
7127           if (context_maybeSet (FLG_INFLOOPS)
7128               || context_maybeSet (FLG_INFLOOPSUNCON))
7129             {
7130               /*
7131               ** check that some variable in the predicate is set by the body
7132               ** if the predicate uses any variables
7133               */
7134               
7135               checkInfiniteLoop (test, b);
7136             }
7137
7138           exprNode_mergeUSs (ret, b);
7139
7140           if (exprNode_isDefined (b))
7141             {
7142               ret->exitCode = exitkind_makeConditional (b->exitCode);
7143             }
7144         }
7145     }
7146   
7147   ret->edata = exprData_makePair (t, b);
7148   ret->kind = XPR_WHILE;
7149
7150   if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7151     {
7152       voptgenerror
7153         (FLG_CONTROL,
7154          message ("Predicate always exits: %s", exprNode_unparse (t)),
7155          exprNode_loc (t));
7156     }
7157
7158   ret->exitCode = XK_NEVERESCAPE;
7159
7160   /*
7161   ** If loop is infinite, and there is no break inside, 
7162   ** exit code is never reach. 
7163   */
7164
7165   if (exprNode_knownIntValue (t))
7166     {
7167       if (!exprNode_isZero (t)) 
7168         {
7169           if (exprNode_isDefined (b)) 
7170             {
7171               if (!b->canBreak) 
7172                 {
7173                   /* Really, it means never reached. */
7174                   ret->exitCode = XK_MUSTEXIT;
7175                 }
7176             }
7177         }
7178     } 
7179   else 
7180     {
7181       ;
7182     }
7183
7184   ret->canBreak = FALSE;
7185   ret->mustBreak = FALSE;
7186
7187   return ret; 
7188 }
7189
7190 /*
7191 ** do { b } while (t);
7192 ** 
7193 ** note: body passed as first argument 
7194 */
7195
7196 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7197 {
7198   exprNode ret;
7199   
7200   if (exprNode_isError (t))
7201     {
7202       if (exprNode_isError (b))
7203         {
7204           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7205         }
7206       else
7207         {
7208           ret = exprNode_createPartialCopy (b);
7209
7210           ret->exitCode = exitkind_makeConditional (b->exitCode);
7211           exprNode_checkUse (ret, b->sref, b->loc);
7212           ret->exitCode = b->exitCode;
7213           ret->canBreak = b->canBreak;
7214           ret->mustBreak = b->mustBreak;
7215         }
7216     }
7217   else
7218     {
7219       ret = exprNode_createPartialCopy (t);
7220       exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7221       
7222       if (!exprNode_isError (b)) 
7223         {
7224           /*
7225           ** forgot the copy's --- why wasn't this detected??
7226           */
7227
7228           ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7229           ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7230           ret->uses = sRefSet_copyInto (ret->uses, b->uses);  
7231
7232           /* left this out --- causes and aliasing bug (infinite loop)
7233              should be detected?? */
7234
7235           exprNode_checkUse (ret, b->sref, b->loc);
7236           exprNode_mergeUSs (ret, t);
7237           exprNode_checkUse (ret, t->sref, t->loc);
7238
7239           ret->exitCode = b->exitCode;
7240           ret->canBreak = b->canBreak;
7241           ret->mustBreak = b->mustBreak;
7242         }
7243     }
7244   
7245   context_exitDoWhileClause (t);
7246
7247   ret->kind = XPR_DOWHILE;
7248   ret->edata = exprData_makePair (t, b);
7249   return ret;
7250 }
7251
7252 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7253 {
7254   exprNode ret;
7255   bool emptyErr = FALSE;
7256
7257   if (context_maybeSet (FLG_FOREMPTY))
7258     {
7259       if (exprNode_isEmptyStatement (body))
7260         {
7261           emptyErr = optgenerror 
7262             (FLG_FOREMPTY,
7263              cstring_makeLiteral
7264              ("Body of for statement is empty"),
7265              exprNode_loc (body));
7266         }
7267     }
7268
7269   if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7270     {
7271       if (exprNode_isDefined (body)
7272           && !exprNode_isBlock (body))
7273         {
7274           if (context_inIterDef ()
7275               && (body->kind == XPR_STMTLIST
7276                   || body->kind == XPR_TOK))
7277             {
7278               ; /* no error */
7279             }
7280           else
7281             {
7282               voptgenerror (FLG_FORBLOCK,
7283                             message
7284                             ("Body of for statement is not a block: %s",
7285                              exprNode_unparse (body)),
7286                             exprNode_loc (body));
7287             }
7288         }
7289     }
7290
7291   /*
7292   ** for ud purposes:  (alreadly) init -> test -> (now) LOOP: body + inc + test
7293   */
7294
7295   if (exprNode_isError (body))
7296     {
7297       ret = exprNode_createPartialCopy (inc);
7298     }
7299   else
7300     {
7301       ret = exprNode_createPartialCopy (body);
7302       
7303       ret->exitCode = exitkind_makeConditional (body->exitCode);
7304
7305             exprNode_mergeUSs (inc, body);
7306       
7307       if (exprNode_isDefined (inc))
7308         {
7309           exprNode tmp;
7310
7311           context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7312      
7313           
7314           tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7315           exprNode_freeShallow (tmp); 
7316
7317           context_clearMessageAnnote ();
7318           context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7319
7320           tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7321           exprNode_freeShallow (tmp);
7322
7323           context_clearMessageAnnote ();
7324
7325           ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7326           ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7327           ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7328         }
7329     }
7330
7331   ret->kind = XPR_FOR;
7332   ret->edata = exprData_makePair (inc, body);
7333
7334   if (exprNode_isDefined (inc)) {
7335     exprNode test = exprData_getTripleTest (inc->edata);
7336
7337     if (exprNode_isUndefined (test)) {
7338       if (exprNode_isDefined (body)) {
7339         if (!body->canBreak) {
7340           /* Really, it means never reached. */
7341           ret->exitCode = XK_MUSTEXIT;
7342         }
7343       }
7344     }
7345   }
7346
7347   return (ret);
7348 }
7349
7350 /*
7351 ** for (init; test; inc)
7352 ** ==>
7353 ** init;
7354 ** while (test) { body; inc; } 
7355 **
7356 ** Now: check use of init (may set vars for test)
7357 **      check use of test
7358 **      no checks on inc
7359 _*/
7360
7361 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7362 {
7363   exprNode test;
7364
7365   if (exprNode_isError (pred)) return guardSet_undefined;
7366
7367   llassert (pred->kind == XPR_FORPRED);
7368
7369   test = exprData_getTripleTest (pred->edata);
7370
7371   if (!exprNode_isError (test))
7372     {
7373       return (test->guards);
7374     }
7375
7376   return guardSet_undefined;
7377 }
7378
7379 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7380 {
7381   exprNode ret = exprNode_createSemiCopy (test);
7382
7383   if (exprNode_isDefined (test))
7384     {
7385       exprNode_copySets (ret, test);
7386       exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7387       exprNode_checkUse (ret, test->sref, test->loc);
7388       
7389       exprNode_produceGuards (test);
7390       
7391       ret->guards = guardSet_copy (test->guards);
7392     }
7393
7394   ret->edata = exprData_makeSingle (test);
7395   ret->kind = XPR_WHILEPRED;
7396   return ret;
7397 }
7398
7399 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test, 
7400                            /*@only@*/ exprNode inc)
7401 {
7402   exprNode ret;
7403   
7404   /*
7405   ** for ud purposes:  init -> test -> LOOP: [ body, inc ]
7406   */
7407   
7408   exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7409
7410   if (!exprNode_isError (inc)) 
7411     {
7412       ret = exprNode_createPartialCopy (inc);
7413     }
7414   else 
7415     {
7416       if (!exprNode_isError (init)) 
7417         {
7418           ret = exprNode_createPartialCopy (init);
7419         }
7420       else if (!exprNode_isError (test)) 
7421         {
7422           ret = exprNode_createPartialCopy (test);
7423         }
7424       else 
7425         {
7426           ret = exprNode_createUnknown ();
7427         }
7428     }
7429
7430   exprNode_mergeUSs (ret, init);
7431
7432   if (exprNode_isDefined (init))
7433     {
7434       exprNode_checkUse (ret, init->sref, init->loc);
7435     }
7436
7437   exprNode_mergeUSs (ret, test);
7438
7439   if (exprNode_isDefined (test))
7440     {
7441       exprNode_checkUse (ret, test->sref, test->loc);
7442     }
7443
7444   ret->kind = XPR_FORPRED;
7445   ret->edata = exprData_makeFor (init, test, inc); 
7446   return (ret);
7447 }
7448
7449 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7450 {
7451   exprNode ret = exprNode_createUnknown ();
7452
7453   if (context_inMacro ())
7454     {
7455       voptgenerror (FLG_MACROSTMT,
7456                     message ("Macro %s uses goto (not functional)", 
7457                              context_inFunctionName ()),
7458                     g_currentloc);
7459     }
7460   
7461   ret->kind = XPR_GOTO;
7462   ret->edata = exprData_makeLiteral (label);
7463   ret->mustBreak = TRUE;
7464   ret->exitCode = XK_GOTO;
7465   ret->canBreak = TRUE;
7466   return ret;
7467 }
7468
7469 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7470 {
7471   exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7472
7473   ret->kind = XPR_CONTINUE;
7474   ret->edata = exprData_makeTok (l);
7475   ret->canBreak = TRUE;
7476   ret->mustBreak = TRUE;
7477
7478   if (qcontinue == QSAFEBREAK)
7479     {
7480       ; /* no checking */
7481     }
7482   else if (qcontinue == QINNERCONTINUE)
7483     {
7484       if (!context_inDeepLoop ())
7485         {
7486           voptgenerror 
7487             (FLG_LOOPLOOPCONTINUE,
7488              cstring_makeLiteral ("Continue statement marked with innercontinue "
7489                                   "is not inside a nested loop"),
7490              exprNode_loc (ret));
7491         }
7492     }
7493   else if (qcontinue == BADTOK)
7494     {
7495       if (context_inDeepLoop ())
7496         {
7497           voptgenerror 
7498             (FLG_LOOPLOOPCONTINUE,
7499              cstring_makeLiteral ("Continue statement in nested loop"),
7500              exprNode_loc (ret));
7501         }
7502     }
7503   else
7504     {
7505       llbuglit ("exprNode_continue: bad qcontinue");
7506     }
7507
7508   return ret;
7509 }
7510
7511 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7512 {
7513   exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7514   clause breakClause = context_breakClause ();
7515   
7516   ret->kind = XPR_BREAK;
7517   ret->edata = exprData_makeTok (l);
7518   ret->canBreak = TRUE;
7519   ret->mustBreak = TRUE;
7520   
7521   if (breakClause == NOCLAUSE)
7522     {
7523       voptgenerror 
7524         (FLG_SYNTAX,
7525          cstring_makeLiteral ("Break not inside while, for or switch statement"),
7526          exprNode_loc (ret));
7527     }
7528   else
7529     {
7530       if (bqual != BADTOK)
7531         {
7532           switch (bqual)
7533             {
7534             case QSAFEBREAK:
7535               break;
7536             case QINNERBREAK:
7537               if (breakClause == SWITCHCLAUSE)
7538                 {
7539                   if (!context_inDeepSwitch ())
7540                     {
7541                       voptgenerror (FLG_SYNTAX,
7542                                     cstring_makeLiteral 
7543                                     ("Break preceded by innerbreak is not in a deep switch"),
7544                                     exprNode_loc (ret));
7545                     }
7546                 }
7547               else 
7548                 {
7549                   if (!context_inDeepLoop ())
7550                     {
7551                       voptgenerror (FLG_SYNTAX,
7552                                     cstring_makeLiteral 
7553                                     ("Break preceded by innerbreak is not in a deep loop"),
7554                                     exprNode_loc (ret));
7555                     }
7556                 }
7557               break;
7558             case QLOOPBREAK:
7559               if (breakClause == SWITCHCLAUSE)
7560                 {
7561                   voptgenerror (FLG_SYNTAX,
7562                                 cstring_makeLiteral 
7563                                 ("Break preceded by loopbreak is breaking a switch"),
7564                                 exprNode_loc (ret));
7565                 }
7566               break;
7567             case QSWITCHBREAK:
7568               if (breakClause != SWITCHCLAUSE)
7569                 {
7570                   voptgenerror 
7571                     (FLG_SYNTAX,
7572                      message ("Break preceded by switchbreak is breaking %s",
7573                               cstring_makeLiteralTemp 
7574                               ((breakClause == WHILECLAUSE
7575                                 || breakClause == DOWHILECLAUSE) ? "a while loop"
7576                                : (breakClause == FORCLAUSE) ? "a for loop"
7577                                : (breakClause == ITERCLAUSE) ? "an iterator"
7578                                : "<error loop>")),
7579                      exprNode_loc (ret));
7580                 }
7581               break;
7582             BADDEFAULT;
7583             }
7584         }
7585       else
7586         {
7587           if (breakClause == SWITCHCLAUSE)
7588             {
7589               clause nextBreakClause = context_nextBreakClause ();
7590
7591               switch (nextBreakClause)
7592                 {
7593                 case NOCLAUSE: break;
7594                 case WHILECLAUSE:
7595                 case DOWHILECLAUSE:
7596                 case FORCLAUSE:
7597                 case ITERCLAUSE:
7598                   voptgenerror 
7599                     (FLG_LOOPSWITCHBREAK,
7600                      cstring_makeLiteral ("Break statement in switch inside loop"),
7601                      exprNode_loc (ret));
7602                   break;
7603                 case SWITCHCLAUSE:
7604                   voptgenerror 
7605                     (FLG_SWITCHSWITCHBREAK,
7606                      cstring_makeLiteral ("Break statement in switch inside switch"),
7607                      exprNode_loc (ret));
7608                   break;
7609                 BADDEFAULT;
7610                 }
7611             }
7612           else
7613             {
7614               if (context_inDeepLoop ())
7615                 {
7616                   voptgenerror 
7617                     (FLG_LOOPLOOPBREAK,
7618                      cstring_makeLiteral ("Break statement in nested loop"),
7619                      exprNode_loc (ret));
7620                 }
7621               else 
7622                 {
7623                   if (context_inDeepLoopSwitch ())
7624                     {
7625                       voptgenerror 
7626                         (FLG_SWITCHLOOPBREAK,
7627                          cstring_makeLiteral ("Break statement in loop inside switch"),
7628                          exprNode_loc (ret));
7629                     }
7630                 }
7631             }
7632         }
7633     }
7634
7635   return ret;
7636 }
7637
7638 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7639 {
7640   fileloc loc = lltok_getLoc (t);
7641   exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7642   
7643   context_returnFunction ();
7644   exprChecks_checkNullReturn (loc);
7645
7646   ret->kind = XPR_NULLRETURN;
7647   ret->edata = exprData_makeTok (t);
7648   ret->exitCode = XK_MUSTRETURN;
7649   return ret;
7650 }
7651
7652 exprNode exprNode_return (/*@only@*/ exprNode e)
7653 {
7654   exprNode ret;
7655   
7656   if (exprNode_isError (e))
7657     {
7658       ret = exprNode_createUnknown ();
7659     }
7660   else
7661     {
7662       ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7663
7664       exprNode_checkUse (ret, e->sref, e->loc);
7665       exprNode_checkReturn (e);
7666     }
7667
7668   context_returnFunction ();
7669   ret->kind = XPR_RETURN;
7670   ret->edata = exprData_makeSingle (e);
7671   ret->exitCode = XK_MUSTRETURN;
7672
7673   return (ret);
7674 }
7675
7676 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7677 {
7678   exprNode ret;
7679
7680   if (exprNode_isError (e1)) 
7681     {
7682       if (exprNode_isError (e2))
7683         {
7684           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7685         }
7686       else
7687         {
7688           ret = exprNode_createPartialCopy (e2);
7689           exprNode_checkUse (ret, e2->sref, e2->loc);
7690           ret->sref = e2->sref;
7691         }
7692     }
7693   else
7694     {
7695       ret = exprNode_createPartialCopy (e1);
7696
7697       exprNode_checkUse (ret, e1->sref, e1->loc);
7698
7699       if (!exprNode_isError (e2))
7700         {
7701           exprNode_mergeUSs (ret, e2);
7702           exprNode_checkUse (ret, e2->sref, e2->loc);
7703           ret->sref = e2->sref;
7704         }
7705     }
7706
7707   ret->kind = XPR_COMMA;
7708   ret->edata = exprData_makePair (e1, e2);
7709   
7710   if (exprNode_isDefined (e1))
7711     {
7712       if (exprNode_isDefined (e2))
7713         {
7714           ret->typ = e2->typ; 
7715
7716           if (exprNode_mustEscape (e1) || e1->mustBreak)
7717             {
7718               voptgenerror 
7719                 (FLG_UNREACHABLE,
7720                  message ("Second clause of comma expression is unreachable: %s",
7721                           exprNode_unparse (e2)), 
7722                  exprNode_loc (e2));
7723             }
7724           
7725           ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7726           ret->mustBreak = e1->mustBreak || e2->mustBreak;
7727           ret->canBreak = e1->canBreak || e2->canBreak;
7728         }
7729       else
7730         {
7731           if (exprNode_mustEscape (e1) || e1->mustBreak)
7732             {
7733               voptgenerror 
7734                 (FLG_UNREACHABLE,
7735                  message ("Second clause of comma expression is unreachable: %s",
7736                           exprNode_unparse (e2)), 
7737                  exprNode_loc (e2));
7738             }
7739           
7740           ret->exitCode = e1->exitCode;
7741           ret->canBreak = e1->canBreak;
7742         }
7743     }
7744   else
7745     {
7746       if (exprNode_isDefined (e2))
7747         {
7748           ret->exitCode = e2->exitCode;
7749           ret->mustBreak = e2->mustBreak;
7750           ret->canBreak = e2->canBreak;
7751         }
7752     }
7753
7754   return (ret);
7755 }
7756
7757 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7758 {
7759   ctype t1 = exprNode_getType (el);
7760   ctype t2 = exprNode_getType (val);
7761   bool hasError = FALSE;
7762   
7763   if (ctype_isUnknown (t1))
7764     {
7765       voptgenerror (FLG_IMPTYPE,
7766                     message ("Variable has unknown (implicitly int) type: %s",
7767                              exprNode_unparse (el)),
7768                     el->loc);
7769       
7770       t1 = ctype_int;
7771       el->typ = ctype_int;
7772     }
7773
7774   if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7775     {
7776       exprNodeList vals = exprData_getArgs (val->edata);
7777
7778       if (ctype_isRealAP (t1))
7779         {
7780           int i = 0;
7781           int nerrors = 0;
7782
7783           /*@i423 check number of entries int a[3] = { 1, 2, 3, 4 } ; */
7784
7785           exprNodeList_elements (vals, oneval)
7786             {
7787               cstring istring = message ("%d", i);
7788               exprNode newel =
7789                 exprNode_arrayFetch 
7790                   (exprNode_fakeCopy (el),
7791                    exprNode_numLiteral (ctype_int, istring,
7792                                         fileloc_copy (el->loc), i));
7793               
7794               if (exprNode_isDefined (newel))
7795                 {
7796                   if (exprNodeList_size (vals) == 1
7797                       && ctype_isString (exprNode_getType (oneval))
7798                       && ctype_isChar (exprNode_getType (newel)))
7799                     {
7800                       exprNode_freeIniter (newel);
7801                     }
7802                   else
7803                     {
7804                       if (exprNode_checkOneInit (newel, oneval))
7805                         {
7806                           hasError = TRUE;
7807                           nerrors++;
7808                           
7809                           if (nerrors > 3 && exprNodeList_size (vals) > 6)
7810                             {
7811                               llgenmsg 
7812                                 (message ("Additional initialization errors "
7813                                           "for %s not reported",
7814                                           exprNode_unparse (el)),
7815                                  exprNode_loc (el));
7816                               exprNode_freeIniter (newel);
7817                               break;
7818                             }
7819                           else
7820                             {
7821                               exprNode_freeIniter (newel);
7822                             }
7823                         }
7824                       else
7825                         {
7826                           exprNode_freeIniter (newel);
7827                         }
7828                     }
7829                 }
7830
7831               cstring_free (istring);
7832               i++;
7833               /*@-branchstate@*/ 
7834             } end_exprNodeList_elements;
7835           /*@=branchstate@*/
7836         }
7837       else if (ctype_isStruct (ctype_realType (t1)))
7838         {
7839           uentryList fields = ctype_getFields (t1);
7840           int i = 0;
7841
7842           if (uentryList_size (fields) != exprNodeList_size (vals))
7843             {
7844               if (uentryList_size (fields) > exprNodeList_size (vals))
7845                 {
7846                   hasError = optgenerror 
7847                     (FLG_FULLINITBLOCK,
7848                      message ("Initializer block for "
7849                               "%s has %d field%&, but %s has %d field%&: %q",
7850                               exprNode_unparse (el),
7851                               exprNodeList_size (vals),
7852                               ctype_unparse (t1),
7853                               uentryList_size (fields),
7854                               exprNodeList_unparse (vals)),
7855                      val->loc);   
7856                 }
7857               else
7858                 {
7859                   hasError = optgenerror 
7860                     (FLG_TYPE,
7861                      message ("Initializer block for "
7862                               "%s has %d field%&, but %s has %d field%&: %q",
7863                               exprNode_unparse (el),
7864                               exprNodeList_size (vals),
7865                               ctype_unparse (t1),
7866                               uentryList_size (fields),
7867                               exprNodeList_unparse (vals)),
7868                      val->loc);   
7869                 }
7870             }
7871           else
7872             {
7873               exprNodeList_elements (vals, oneval)
7874                 {
7875                   uentry thisfield = uentryList_getN (fields, i);
7876                   exprNode newel =
7877                     exprNode_fieldAccessAux (exprNode_fakeCopy (el),
7878                                              exprNode_loc (el),
7879                                              uentry_getName (thisfield));
7880
7881                   if (exprNode_isDefined (newel))
7882                     {
7883                       if (exprNode_checkOneInit (newel, oneval))
7884                         {
7885                           hasError = TRUE;
7886                         }
7887
7888                       exprNode_freeIniter (newel);
7889                     }
7890
7891                   i++;
7892                 } end_exprNodeList_elements;
7893             }
7894         }
7895       else
7896         {
7897           hasError = optgenerror 
7898             (FLG_TYPE,
7899              message ("Initializer block used for "
7900                       "%s where %t is expected: %s",
7901                       exprNode_unparse (el), t1, exprNode_unparse (val)),
7902              val->loc);   
7903         }
7904     }
7905   else
7906     {
7907       if (exprNode_isDefined (val))
7908         {
7909           doAssign (el, val, TRUE);
7910           
7911           if (!exprNode_matchType (t1, val))
7912             {
7913               hasError = gentypeerror 
7914                 (t1, val, t2, el,
7915                  message ("Initial value of %s is type %t, "
7916                           "expects %t: %s",
7917                           exprNode_unparse (el),
7918                           t2, t1, exprNode_unparse (val)),
7919                  val->loc);
7920             }
7921         }
7922     }
7923
7924   return hasError;
7925 }
7926
7927 static exprNode 
7928 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
7929 {
7930   exprNode ret;
7931
7932   if (usymtab_exists (idDecl_observeId (t)))
7933     {
7934       uentry ue = usymtab_lookup (idDecl_observeId (t));
7935       ret = exprNode_createId (ue);
7936
7937       /*@i723 don't do this...but why? */
7938 # if 0
7939       ct = ctype_realishType (ret->typ);
7940
7941       DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
7942
7943       if (ctype_isUnknown (ct)) 
7944         {
7945           if (uentry_isAnyTag (ue))
7946             {
7947               voptgenerror
7948                 (FLG_IMPTYPE,
7949                  message ("%s used but not previously declared: %s",
7950                           uentry_ekindName (ue),
7951                           idDecl_getName (t)),
7952                  g_currentloc);
7953               
7954             }
7955           else
7956             {
7957               voptgenerror
7958                 (FLG_IMPTYPE,
7959                  message ("Variable has unknown (implicitly int) type: %s",
7960                           idDecl_getName (t)),
7961                  g_currentloc);
7962             }
7963
7964           ct = ctype_int;
7965         }
7966 # endif
7967     }
7968   else
7969     {
7970       uentry ue;
7971
7972       DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
7973
7974       ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
7975       /*!! fileloc_copy (g_currentloc)); */
7976       /*@i32!!! should get error without this */
7977       ret = exprNode_fromIdentifierAux (ue);
7978
7979       /*
7980       ** No error - this happens in old style declarations:
7981
7982       voptgenerror
7983         (FLG_UNRECOG,
7984          message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
7985          g_currentloc);
7986
7987       ** 
7988       */
7989     }
7990
7991   exprData_free (ret->edata, ret->kind); 
7992   ret->edata = exprData_undefined;
7993
7994   ret->exitCode = XK_NEVERESCAPE;
7995   ret->mustBreak = FALSE;
7996   ret->kind = XPR_INIT;
7997   return ret;
7998 }
7999   
8000 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8001 {
8002   exprNode ret = exprNode_makeInitializationAux (t);
8003   llassert (ret->edata == exprData_undefined);
8004   ret->edata = exprData_makeInit (t, exprNode_undefined);
8005   return ret;
8006 }
8007
8008 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8009                                       /*@only@*/ exprNode e)
8010 {
8011   uentry ue = usymtab_lookup (idDecl_observeId (t));
8012   exprNode ret = exprNode_makeInitializationAux (t);
8013   fileloc loc = exprNode_loc (e);
8014   
8015   if (exprNode_isError (e)) 
8016     {
8017       e = exprNode_createUnknown ();
8018       idDecl_free (t);
8019
8020       /* error: assume initializer is defined */
8021       sRef_setDefined (ret->sref, g_currentloc); 
8022     }
8023   else
8024     {
8025       ctype ct = ctype_realishType (ret->typ);
8026
8027       /*
8028       ** evs - 9 Apr 1995
8029       **
8030       ** was addSafeUse --- what's the problem?
8031       **
8032       **   int x = 3, y = x ?
8033       */
8034
8035       exprData_free (ret->edata, ret->kind);
8036       ret->edata = exprData_makeInit (t, e);
8037
8038       exprNode_checkUse (ret, e->sref, e->loc);
8039       
8040       if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8041         {
8042           exprNode lhs = exprNode_createId (ue);
8043
8044           /*
8045           ** static storage should be undefined before initializing
8046           */
8047
8048           if (uentry_isStatic (ue))
8049             {
8050               sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8051             }
8052
8053           (void) exprNode_checkOneInit (lhs, e);
8054
8055           if (uentry_isStatic (ue))
8056             {
8057               sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8058             }
8059
8060           exprNode_free (lhs);
8061         }
8062       else
8063         {
8064           if (!exprNode_matchType (ct, e))
8065             {
8066               if (exprNode_isZero (e) && ctype_isArrayPtr (ct)) 
8067                 {
8068                   ;
8069                 }
8070               else
8071                 {
8072                   (void) gentypeerror 
8073                     (exprNode_getType (e), e, exprNode_getType (ret), ret,
8074                      message 
8075                      ("Variable %q initialized to type %t, expects %t: %s",
8076                       uentry_getName (ue), exprNode_getType (e), 
8077                       exprNode_getType (ret),
8078                       exprNode_unparse (e)),
8079                      e->loc);
8080                 }
8081             }
8082         }
8083       
8084       if (uentry_isStatic (ue))
8085         {
8086           sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8087         }
8088
8089       doAssign (ret, e, TRUE);
8090
8091       if (uentry_isStatic (ue))
8092         {
8093           sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8094         }
8095     }
8096
8097   if (context_inIterDef ())
8098     {
8099       /* should check if it is yield */
8100       uentry_setUsed (ue, loc);
8101     }
8102   else
8103     {
8104       ;
8105     }
8106
8107   exprNode_mergeUSs (ret, e);
8108   return ret;
8109 }
8110   
8111 exprNode exprNode_iter (/*@observer@*/ uentry name,
8112                         /*@only@*/ exprNodeList alist, 
8113                         /*@only@*/ exprNode body,
8114                         /*@observer@*/ uentry end)
8115 {
8116   exprNode ret;
8117   cstring iname;
8118
8119   llassert (uentry_isValid (name));
8120
8121   uentry_setUsed (name, exprNode_loc (body));
8122
8123   ret = exprNode_createPartialCopy (body);
8124   iname = uentry_getName (name);
8125
8126   if (uentry_isInvalid (end))
8127     {
8128       llerror (FLG_ITER,
8129                message ("Iter %s not balanced with end_%s", iname, iname));
8130     }
8131   else
8132     {
8133       cstring ename = uentry_getName (end);
8134
8135       if (!cstring_equalPrefix (ename, "end_"))
8136         {
8137           llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s", 
8138                                       iname, iname, ename));
8139         }
8140       else
8141         {
8142           if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8143             {
8144               llerror (FLG_ITER, 
8145                        message ("Iter %s not balanced with end_%s: %s", 
8146                                 iname, iname, ename));
8147             }
8148         }
8149
8150       cstring_free (ename);
8151     }
8152
8153   context_exitIterClause (body);
8154   
8155   ret->kind = XPR_ITER;
8156   ret->edata = exprData_makeIter (name, alist, body, end);
8157
8158   if (uentry_isIter (name))
8159     {
8160       (void) checkArgsReal (name, body, 
8161                             uentry_getParams (name), alist, TRUE, ret);
8162     }
8163
8164   cstring_free (iname);
8165
8166   return ret;
8167 }
8168
8169 exprNode
8170 exprNode_iterNewId (/*@only@*/ cstring s)
8171 {
8172   exprNode e = exprNode_new ();
8173   uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8174
8175   llassert (processingIterVars ());
8176
8177   e->loc = context_getSaveLocation ();
8178
8179   if (fileloc_isUndefined (e->loc))
8180     {
8181       fileloc_free (e->loc);
8182       e->loc = fileloc_copy (g_currentloc);
8183     }
8184
8185   e->uses = sRefSet_new ();
8186   e->sets = sRefSet_new ();
8187   e->msets = sRefSet_new ();
8188   e->kind = XPR_VAR;
8189   e->val = multiVal_unknown ();
8190   e->guards = guardSet_new ();
8191   e->sref = defref;
8192   e->isJumpPoint = FALSE;
8193   e->exitCode = XK_NEVERESCAPE;
8194
8195   /*> missing fields, detected by lclint <*/
8196   e->canBreak = FALSE;
8197   e->mustBreak = FALSE;
8198   e->etext = cstring_undefined;
8199
8200   if (uentry_isYield (ue))
8201     {
8202       uentry uue = uentry_makeVariable (s, uentry_getType (ue), 
8203                                         fileloc_copy (e->loc), 
8204                                         FALSE);
8205       sRef sr;
8206
8207       uue = usymtab_supEntrySrefReturn (uue);
8208
8209       sr = uentry_getSref (uue);
8210       sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8211       sr = uentry_getSref (uue);
8212       sRef_setDefined (sr, e->loc);
8213
8214       e->typ = uentry_getType (uue);      
8215       e->sref = sr;
8216       e->edata = exprData_makeId (uue);
8217       uentry_setUsed (uue, g_currentloc);
8218     }
8219   else
8220     {
8221       uentry uue;
8222
8223       sRef_setGlobalScope ();
8224       uue = uentry_makeVariableLoc (s, ctype_unknown);
8225
8226       e->typ = ctype_unknown;
8227       e->edata = exprData_makeId (uue);
8228
8229       uentry_setUsed (uue, e->loc);
8230       uentry_setHasNameError (uue); 
8231
8232       if (context_getFlag (FLG_REPEATUNRECOG))
8233         {
8234           uentry_markOwned (uue);
8235         }
8236       else
8237         {
8238           usymtab_supGlobalEntry (uue);      
8239         }
8240
8241       sRef_clearGlobalScope ();
8242
8243       voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8244                     e->loc);
8245     }
8246
8247
8248   cstring_free (s);
8249   
8250   exprNode_defineConstraints(e);
8251   return (e);
8252 }
8253
8254 exprNode
8255 exprNode_iterExpr (/*@returned@*/ exprNode e)
8256 {
8257   if (!processingIterVars ())
8258     {
8259       llcontbuglit ("checkIterParam: not in iter");
8260       return e;
8261     }
8262   
8263   if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()), 
8264                                        iterParamNo ())))
8265     {
8266       if (exprNode_isDefined (e))
8267         {
8268           if (fileloc_isDefined (e->loc))
8269             {
8270               voptgenerror
8271                 (FLG_ITER,
8272                  message ("Yield parameter is not simple identifier: %s", 
8273                           exprNode_unparse (e)),
8274                  e->loc);
8275             }
8276           else
8277             {
8278               voptgenerror
8279                 (FLG_ITER,
8280                  message ("Yield parameter is not simple identifier: %s",
8281                           exprNode_unparse (e)),
8282                  g_currentloc);
8283               
8284             }
8285         }
8286     }
8287   return e;
8288 }
8289
8290 exprNode
8291 exprNode_iterId (/*@observer@*/ uentry c)
8292 {
8293   uentry ue;
8294
8295   llassert (processingIterVars ());
8296
8297   ue = uentryList_getN (uentry_getParams (getCurrentIter ()), 
8298                         iterParamNo ());
8299
8300   if (uentry_isYield (ue))
8301     {
8302       ctype ct = uentry_getType (ue);
8303       exprNode e = exprNode_createPlain (ct);
8304       cstring name = uentry_getName (c);
8305       uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8306
8307       uentry_setUsed (ue, g_currentloc);
8308       uentry_setHasNameError (ue); 
8309       
8310       cstring_free (name);
8311       
8312       e->kind = XPR_VAR;
8313       e->edata = exprData_makeId (le);
8314       e->loc = context_getSaveLocation ();
8315       e->sref = uentry_getSref (le);
8316
8317       usymtab_supEntrySref (le);
8318
8319       if (!context_inHeader ())
8320         {
8321           if (optgenerror
8322               (FLG_ITER,
8323                message ("Yield parameter shadows local declaration: %q",
8324                         uentry_getName (c)),
8325                fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8326             {
8327               uentry_showWhereDeclared (c);
8328             }
8329         }
8330
8331       return e;
8332     }
8333
8334   return (exprNode_fromIdentifierAux (c));
8335 }
8336
8337 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8338 {
8339   exprNode ret = exprNode_create (ctype_unknown);
8340
8341   ret->kind = XPR_ITERCALL;
8342   ret->edata = exprData_makeIterCall (name, alist);
8343   
8344   if (uentry_isIter (name))
8345     {
8346       uentryList params = uentry_getParams (name);
8347
8348       if (context_inIterDef () 
8349           && uentryList_size (params) == exprNodeList_size (alist))
8350         {
8351           int i = 0;
8352           
8353           exprNodeList_elements (alist, arg)
8354             {
8355               uentry parg = uentryList_getN (params, i);
8356
8357               if (uentry_isYield (parg))
8358                 {
8359                   uentry ue = exprNode_getUentry (arg);
8360
8361                   if (uentry_isValid (ue))
8362                     {
8363                       ;
8364                     }
8365                 }
8366
8367               i++;
8368             } end_exprNodeList_elements;
8369         }
8370
8371       (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8372       checkUnspecCall (ret, params, alist);
8373     }
8374
8375   return ret;
8376 }
8377
8378 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8379 {
8380   if (exprNode_isDefined (e))
8381     {
8382       /*@access sRef@*/
8383       if (e->sref == defref) /*@noaccess sRef@*/
8384         {
8385           /*@-mods@*/
8386           e->sref = sRef_makeUnknown (); 
8387           sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8388           /*@=mods@*/
8389           return e->sref;
8390         }
8391       else
8392         {
8393           return e->sref;
8394         }
8395     }
8396   else
8397     {
8398       return sRef_undefined;
8399     }
8400 }
8401
8402 /*@observer@*/ cstring
8403 exprNode_unparseFirst (exprNode e)
8404 {
8405   if (exprNode_isDefined (e))
8406     {
8407       cstring ret;
8408
8409       if (e->kind == XPR_STMTLIST
8410           || e->kind == XPR_COMMA || e->kind == XPR_COND)
8411         {
8412           exprNode first = exprData_getPairA (e->edata);
8413
8414           if (exprNode_isDefined (first))
8415             {
8416               return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8417             }
8418           else
8419             {
8420               return (cstring_makeLiteralTemp ("..."));
8421             }
8422         }
8423
8424       ret = cstring_elide (exprNode_unparse (e), 20);
8425       cstring_markOwned (ret);
8426       
8427       return (ret);
8428     }
8429   else
8430     {
8431       return cstring_makeLiteralTemp ("<error>");
8432     }
8433 }
8434
8435 /*@observer@*/ cstring
8436 exprNode_unparse (/*@temp@*/ exprNode e)
8437 {
8438   if (exprNode_isError (e))
8439     {
8440       return cstring_makeLiteralTemp ("<error>");
8441     }
8442
8443   if (cstring_isDefined (e->etext))
8444     {
8445       return e->etext;
8446     }
8447   else
8448     {
8449       cstring ret = exprNode_doUnparse (e);
8450
8451       /*@-modifies@*/ /* benevolent */
8452       e->etext = ret; 
8453       /*@=modifies@*/
8454       return ret;
8455     }
8456 }
8457
8458 /*@observer@*/ fileloc
8459 exprNode_loc (exprNode e)
8460 {
8461   if (exprNode_isError (e))
8462     {
8463       return (g_currentloc);
8464     }
8465   else
8466     {
8467       return (e->loc);
8468     }
8469 }
8470
8471 /*
8472 ** executes exprNode e
8473 **    recursively rexecutes as though in original parse using
8474 **    information in e->edata
8475 */
8476
8477 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8478 {
8479   exprNodeList ret = exprNodeList_new ();
8480
8481   exprNodeList_elements (e, current)
8482     {
8483       exprNodeList_addh (ret, exprNode_effect (current));
8484     } end_exprNodeList_elements;
8485
8486   return ret;
8487 }
8488
8489 static /*@only@*/ exprNode exprNode_effect (exprNode e) 
8490    /*@globals internalState@*/
8491 {
8492   bool innerEffect = inEffect;
8493   exprNode ret;
8494   exprData data;
8495
8496   inEffect = TRUE;
8497
8498   context_clearJustPopped ();
8499
8500   if (exprNode_isError (e))
8501     {
8502       ret = exprNode_undefined;
8503     }
8504   else
8505     {
8506       /*
8507       ** Turn off expose and dependent transfer checking.
8508       ** Need to pass exposed internal nodes,
8509       ** [ copying would be a waste! ]
8510       ** [ Actually, I think I wasted a lot more time than its worth ]
8511       ** [ trying to do this. ]
8512       */
8513
8514       /*@-exposetrans@*/
8515       /*@-observertrans@*/
8516       /*@-dependenttrans@*/
8517       
8518       data = e->edata;
8519       
8520       switch (e->kind)
8521         {
8522         case XPR_PARENS: 
8523           ret = exprNode_addParens (exprData_getUopTok (data), 
8524                                     exprNode_effect (exprData_getUopNode (data)));
8525           break;
8526         case XPR_ASSIGN:
8527           ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)), 
8528                                  exprNode_effect (exprData_getOpB (data)), 
8529                                  exprData_getOpTok (data));
8530           break;
8531         case XPR_INITBLOCK:
8532           ret = exprNode_undefined;
8533           break;
8534         case XPR_CALL:
8535           ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8536                                        exprNodeList_effect (exprData_getArgs (data)));
8537           break;
8538         case XPR_EMPTY:
8539           ret = e;
8540           break;
8541
8542         case XPR_LABEL:
8543           ret = e;
8544           break;
8545
8546         case XPR_CONST:
8547         case XPR_VAR:
8548           {
8549             cstring id = exprData_getId (data);
8550             uentry ue = usymtab_lookupSafe (id);
8551
8552             ret = exprNode_fromIdentifierAux (ue);
8553             ret->loc = fileloc_update (ret->loc, e->loc);
8554             break;
8555           }
8556         case XPR_BODY:
8557           ret = e;
8558           break;
8559         case XPR_FETCH:
8560           ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)), 
8561                                      exprNode_effect (exprData_getPairB (data)));
8562           break;
8563         case XPR_OP:
8564           ret = exprNode_op (exprNode_effect (exprData_getOpA (data)), 
8565                              exprNode_effect (exprData_getOpB (data)), 
8566                              exprData_getOpTok (data));
8567           break;
8568           
8569         case XPR_POSTOP:
8570           ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)), 
8571                                  exprData_getUopTok (data));
8572           break;
8573         case XPR_PREOP:
8574           ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)), 
8575                                 exprData_getUopTok (data));
8576           break;
8577
8578         case XPR_OFFSETOF:
8579         case XPR_SIZEOFT:
8580         case XPR_SIZEOF:
8581         case XPR_ALIGNOFT:
8582         case XPR_ALIGNOF:
8583           ret = e;
8584           break;
8585           
8586         case XPR_VAARG:
8587           ret = exprNode_vaArg (exprData_getCastTok (data),
8588                                 exprNode_effect (exprData_getCastNode (data)),
8589                                 exprData_getCastType (data));
8590           break;
8591           
8592         case XPR_CAST:
8593           ret = exprNode_cast (exprData_getCastTok (data), 
8594                                exprNode_effect (exprData_getCastNode (data)), 
8595                                exprData_getCastType (data));
8596           break;
8597         case XPR_ITERCALL:
8598           ret = exprNode_iterStart (exprData_getIterCallIter (data),
8599                                     exprNodeList_effect 
8600                                     (exprData_getIterCallArgs (data)));
8601           break;
8602           
8603         case XPR_ITER:
8604           ret = exprNode_iter (exprData_getIterSname (data),
8605                                exprNodeList_effect (exprData_getIterAlist (data)),
8606                                exprNode_effect (exprData_getIterBody (data)),
8607                                exprData_getIterEname (data));
8608           break;
8609           
8610         case XPR_FOR:
8611           ret = exprNode_for (exprNode_effect (exprData_getPairA (data)), 
8612                               exprNode_effect (exprData_getPairB (data)));
8613           break;
8614           
8615         case XPR_FORPRED:
8616           ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8617                                   exprNode_effect (exprData_getTripleTest (data)),
8618                                   exprNode_effect (exprData_getTripleInc (data)));
8619           break;
8620           
8621         case XPR_TOK:
8622           ret = exprNode_createTok (exprData_getTok (data));
8623           break;
8624           
8625         case XPR_GOTO:
8626           ret = exprNode_goto (exprData_getLiteral (data));
8627           ret->loc = fileloc_update (ret->loc, e->loc);
8628           break;
8629           
8630         case XPR_CONTINUE:
8631           ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8632           break;
8633           
8634         case XPR_BREAK:
8635           ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8636           break;
8637           
8638         case XPR_RETURN:
8639           ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8640           break;
8641           
8642         case XPR_NULLRETURN:
8643           ret = exprNode_nullReturn (exprData_getTok (data));
8644           break;
8645           
8646         case XPR_COMMA:
8647           ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8648                                 exprNode_effect (exprData_getPairB (data)));
8649           break;
8650           
8651         case XPR_COND:
8652           ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8653                                exprNode_effect (exprData_getTripleTrue (data)),
8654                                exprNode_effect (exprData_getTripleFalse (data)));
8655           break;
8656         case XPR_IF:
8657           ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8658                              exprNode_effect (exprData_getPairB (data)));
8659           break;
8660           
8661         case XPR_IFELSE:
8662           ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8663                                  exprNode_effect (exprData_getTripleTrue (data)),
8664                                  exprNode_effect (exprData_getTripleFalse (data)));
8665           break;
8666         case XPR_WHILEPRED:
8667           ret = exprNode_whilePred (exprData_getSingle (data));
8668           break;
8669           
8670         case XPR_WHILE:
8671           ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8672                                 exprNode_effect (exprData_getPairB (data)));
8673           break;
8674           
8675         case XPR_DOWHILE:
8676           ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8677                                   exprNode_effect (exprData_getPairB (data)));
8678           break;
8679
8680         case XPR_BLOCK:
8681           ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8682           break;          
8683
8684         case XPR_STMT:
8685           ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8686                                     exprData_getUopTok (data));
8687           break;
8688           
8689         case XPR_STMTLIST:
8690           ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8691                                  exprNode_effect (exprData_getPairB (data)));
8692           break;
8693           
8694         case XPR_FTCASE:
8695         case XPR_CASE:
8696           ret = exprNode_caseMarker 
8697             (exprNode_effect (exprData_getSingle (data)),
8698              TRUE);
8699           break;
8700           
8701         case XPR_FTDEFAULT:
8702         case XPR_DEFAULT:
8703           ret = exprNode_createTok (exprData_getTok (data));
8704           break;
8705           
8706         case XPR_SWITCH:
8707           ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8708                                  exprNode_effect (exprData_getPairB (data)));
8709           break;
8710           
8711         case XPR_INIT:
8712           ret = exprNode_makeInitialization
8713             (exprData_getInitId (data),
8714              exprNode_effect (exprData_getInitNode (data)));
8715           break;
8716           
8717         case XPR_FACCESS:
8718           ret = exprNode_fieldAccessAux
8719             (exprNode_effect (exprData_getFieldNode (data)),
8720              exprNode_loc (exprData_getFieldNode (data)),
8721              cstring_copy (exprData_getFieldName (data)));
8722           break;
8723           
8724         case XPR_ARROW:
8725           ret = exprNode_arrowAccessAux
8726             (exprNode_effect (exprData_getFieldNode (data)),
8727              exprNode_loc (exprData_getFieldNode (data)),
8728              cstring_copy (exprData_getFieldName (data)));
8729           break;
8730           
8731         case XPR_STRINGLITERAL:
8732           ret = e;
8733           break;
8734           
8735         case XPR_NUMLIT:
8736           ret = e;
8737           break;
8738
8739         case XPR_NODE:
8740           ret = e;
8741           break;
8742           /*@-branchstate@*/ 
8743         } 
8744       /*@=branchstate@*/
8745       /*@=observertrans@*/
8746       /*@=exposetrans@*/
8747       /*@=dependenttrans@*/
8748     }
8749
8750   if (!innerEffect) 
8751     {
8752       inEffect = FALSE;
8753     }
8754
8755   return ret;
8756 }
8757
8758 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8759 {
8760   cstring ret;
8761   exprData data;
8762
8763   if (exprNode_isError (e))
8764     {
8765       return cstring_undefined;
8766     }
8767
8768   data = e->edata;
8769
8770   switch (e->kind)
8771     {
8772     case XPR_PARENS: 
8773       ret = exprNode_rootVarName (exprData_getUopNode (data));
8774       break;
8775     case XPR_ASSIGN:
8776       ret = exprNode_rootVarName (exprData_getOpA (data));
8777       break;
8778     case XPR_CONST:
8779     case XPR_VAR:
8780       ret = exprData_getId (data);
8781       break;
8782     case XPR_INIT:
8783       ret = idDecl_getName (exprData_getInitId (data));
8784       break;
8785     case XPR_LABEL:
8786     case XPR_TOK:
8787     case XPR_ITERCALL:
8788     case XPR_EMPTY:
8789     case XPR_CALL:
8790     case XPR_INITBLOCK:
8791     case XPR_BODY:
8792     case XPR_FETCH:
8793     case XPR_OP:
8794     case XPR_POSTOP:
8795     case XPR_PREOP:
8796     case XPR_OFFSETOF:
8797     case XPR_ALIGNOFT:
8798     case XPR_ALIGNOF:
8799     case XPR_SIZEOFT:
8800     case XPR_SIZEOF:
8801     case XPR_VAARG:
8802     case XPR_CAST:
8803     case XPR_ITER:
8804     case XPR_FOR:
8805     case XPR_FORPRED:
8806     case XPR_BREAK:
8807     case XPR_RETURN:
8808     case XPR_NULLRETURN:
8809     case XPR_COMMA:
8810     case XPR_COND:
8811     case XPR_IF:
8812     case XPR_IFELSE:
8813     case XPR_WHILE:
8814     case XPR_WHILEPRED:
8815     case XPR_DOWHILE:
8816     case XPR_GOTO:
8817     case XPR_CONTINUE:
8818     case XPR_FTDEFAULT:
8819     case XPR_DEFAULT:
8820     case XPR_SWITCH:
8821     case XPR_FTCASE:
8822     case XPR_CASE:
8823     case XPR_BLOCK:
8824     case XPR_STMT:
8825     case XPR_STMTLIST:
8826     case XPR_FACCESS:
8827     case XPR_ARROW:
8828     case XPR_NODE:
8829     case XPR_NUMLIT:
8830     case XPR_STRINGLITERAL:
8831       ret = cstring_undefined;
8832       break;
8833     }
8834
8835   return ret;
8836 }
8837
8838 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8839 {
8840   cstring ret;
8841   exprData data;
8842
8843   if (exprNode_isError (e))
8844     {
8845       static /*@only@*/ cstring error = cstring_undefined;
8846
8847       if (!cstring_isDefined (error))
8848         {
8849           error = cstring_makeLiteral ("<error>");
8850         }
8851       
8852       return error;
8853     }
8854
8855   data = e->edata;
8856
8857   switch (e->kind)
8858     {
8859     case XPR_PARENS: 
8860       ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8861       break;
8862     case XPR_ASSIGN:
8863       ret = message ("%s %s %s",
8864                      exprNode_unparse (exprData_getOpA (data)), 
8865                      lltok_unparse (exprData_getOpTok (data)),
8866                      exprNode_unparse (exprData_getOpB (data)));
8867       break;
8868     case XPR_CALL:
8869       ret = message ("%s(%q)",
8870                      exprNode_unparse (exprData_getFcn (data)), 
8871                      exprNodeList_unparse (exprData_getArgs (data)));
8872       break;
8873     case XPR_INITBLOCK:
8874       ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8875       break;
8876     case XPR_EMPTY:
8877       ret = cstring_undefined;
8878       break;
8879     case XPR_LABEL:
8880       ret = message ("%s:", exprData_getId (data));
8881       break;
8882     case XPR_CONST:
8883     case XPR_VAR:
8884       ret = cstring_copy (exprData_getId (data));
8885       break;
8886     case XPR_FETCH:
8887       ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8888                      exprNode_unparse (exprData_getPairB (data)));
8889       break;
8890     case XPR_BODY:
8891       ret = message ("<body>");
8892       break;
8893     case XPR_OP:
8894       ret = message ("%s %s %s",
8895                      exprNode_unparse (exprData_getOpA (data)), 
8896                      lltok_unparse (exprData_getOpTok (data)),
8897                      exprNode_unparse (exprData_getOpB (data))); 
8898       break;
8899       
8900     case XPR_PREOP: 
8901       ret = message ("%s%s",
8902                      lltok_unparse (exprData_getUopTok (data)),
8903                      exprNode_unparse (exprData_getUopNode (data))); 
8904       break;
8905
8906     case XPR_POSTOP:
8907       ret = message ("%s%s",
8908                      exprNode_unparse (exprData_getUopNode (data)),
8909                      lltok_unparse (exprData_getUopTok (data))); 
8910       break;
8911       
8912     case XPR_OFFSETOF:
8913       ret = message ("offsetof(%s,%q)", 
8914                      ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8915                      cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8916       break;
8917
8918     case XPR_SIZEOFT:
8919       ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8920       break;
8921       
8922     case XPR_SIZEOF:
8923       ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8924       break;
8925
8926     case XPR_ALIGNOFT:
8927       ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8928       break;
8929       
8930     case XPR_ALIGNOF:
8931       ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8932       break;
8933       
8934     case XPR_VAARG:
8935       ret = message ("va_arg(%s, %q)", 
8936                      exprNode_unparse (exprData_getCastNode (data)),
8937                      qtype_unparse (exprData_getCastType (data)));
8938       break;
8939       
8940     case XPR_ITERCALL:
8941       ret = message ("%q(%q)", 
8942                      uentry_getName (exprData_getIterCallIter (data)),
8943                      exprNodeList_unparse (exprData_getIterCallArgs (data)));
8944       break;
8945     case XPR_ITER:
8946       ret = message ("%q(%q) %s %q",
8947                      uentry_getName (exprData_getIterSname (data)),
8948                      exprNodeList_unparse (exprData_getIterAlist (data)),
8949                      exprNode_unparse (exprData_getIterBody (data)),
8950                      uentry_getName (exprData_getIterEname (data)));
8951       break;
8952     case XPR_CAST:
8953       ret = message ("(%q)%s", 
8954                      qtype_unparse (exprData_getCastType (data)),
8955                      exprNode_unparse (exprData_getCastNode (data)));
8956       break;
8957       
8958     case XPR_FOR:
8959       ret = message ("%s %s", 
8960                      exprNode_unparse (exprData_getPairA (data)), 
8961                      exprNode_unparse (exprData_getPairB (data)));
8962       break;
8963
8964     case XPR_FORPRED:
8965             ret = message ("for (%s; %s; %s)",
8966                      exprNode_unparse (exprData_getTripleInit (data)),
8967                      exprNode_unparse (exprData_getTripleTest (data)),
8968                      exprNode_unparse (exprData_getTripleInc (data)));
8969       break;
8970       
8971     case XPR_GOTO:
8972       ret = message ("goto %s", exprData_getLiteral (data));
8973       break;
8974
8975     case XPR_CONTINUE:
8976       ret = cstring_makeLiteral ("continue");
8977       break;
8978
8979     case XPR_BREAK:
8980       ret = cstring_makeLiteral ("break");
8981       break;
8982
8983     case XPR_RETURN:
8984       ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
8985       break;
8986
8987     case XPR_NULLRETURN:
8988       ret = cstring_makeLiteral ("return");
8989       break;
8990
8991     case XPR_COMMA:
8992       ret = message ("%s, %s", 
8993                      exprNode_unparse (exprData_getPairA (data)),
8994                      exprNode_unparse (exprData_getPairB (data)));
8995       break;
8996       
8997     case XPR_COND:
8998       ret = message ("%s ? %s : %s",
8999                      exprNode_unparse (exprData_getTriplePred (data)),
9000                      exprNode_unparse (exprData_getTripleTrue (data)),
9001                      exprNode_unparse (exprData_getTripleFalse (data)));
9002       break;
9003     case XPR_IF:
9004       ret = message ("if (%s) %s", 
9005                      exprNode_unparse (exprData_getPairA (data)),
9006                      exprNode_unparse (exprData_getPairB (data)));
9007       break;
9008       
9009     case XPR_IFELSE:
9010       ret = message ("if (%s) %s else %s",
9011                      exprNode_unparse (exprData_getTriplePred (data)),
9012                      exprNode_unparse (exprData_getTripleTrue (data)),
9013                      exprNode_unparse (exprData_getTripleFalse (data)));
9014       break;
9015     case XPR_WHILE:
9016       ret = message ("while (%s) %s",
9017                      exprNode_unparse (exprData_getPairA (data)),
9018                      exprNode_unparse (exprData_getPairB (data)));
9019       break;
9020
9021     case XPR_WHILEPRED:
9022       ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9023       break;
9024
9025     case XPR_TOK:
9026       ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9027       break;
9028
9029     case XPR_DOWHILE:
9030       ret = message ("do { %s } while (%s)",
9031                      exprNode_unparse (exprData_getPairB (data)),
9032                      exprNode_unparse (exprData_getPairA (data)));
9033       break;
9034       
9035     case XPR_BLOCK:
9036       ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9037       break;
9038
9039     case XPR_STMT:
9040       ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9041       break;
9042
9043     case XPR_STMTLIST:
9044       ret = message ("%s; %s", 
9045                      exprNode_unparse (exprData_getPairA (data)),
9046                      exprNode_unparse (exprData_getPairB (data)));
9047       break;
9048       
9049     case XPR_FTDEFAULT:
9050     case XPR_DEFAULT:
9051       ret = cstring_makeLiteral ("default:");
9052       break;
9053
9054     case XPR_SWITCH:
9055       ret = message ("switch (%s) %s", 
9056                      exprNode_unparse (exprData_getPairA (data)),
9057                      exprNode_unparse (exprData_getPairB (data)));
9058       break;
9059
9060     case XPR_FTCASE:
9061     case XPR_CASE:
9062       ret = message ("case %s:", 
9063                      exprNode_unparse (exprData_getSingle (data)));
9064       break;
9065       
9066     case XPR_INIT:
9067       if (exprNode_isError (exprData_getInitNode (data)))
9068         {
9069           ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9070         }
9071       else
9072         {
9073           ret = message ("%q = %s",
9074                          idDecl_unparseC (exprData_getInitId (data)),
9075                          exprNode_unparse (exprData_getInitNode (data)));
9076         }
9077       break;
9078       
9079     case XPR_FACCESS:
9080       ret = message ("%s.%s",
9081                      exprNode_unparse (exprData_getFieldNode (data)),
9082                      exprData_getFieldName (data));
9083       break;
9084       
9085     case XPR_ARROW:
9086             ret = message ("%s->%s",
9087                      exprNode_unparse (exprData_getFieldNode (data)),
9088                      exprData_getFieldName (data));
9089       break;
9090
9091     case XPR_STRINGLITERAL:
9092       ret = message ("\"%s\"", exprData_getLiteral (data));
9093       break;
9094
9095     case XPR_NUMLIT:
9096       ret = cstring_copy (exprData_getLiteral (data));
9097       break;
9098
9099     case XPR_NODE:
9100       ret = cstring_makeLiteral ("<node>");
9101       break;
9102     }
9103
9104   return ret;
9105 }
9106
9107 bool
9108 exprNode_isInitializer (exprNode e)
9109 {
9110   return (exprNode_isDefined (e)
9111           && e->kind == XPR_INIT);
9112 }
9113
9114 bool 
9115 exprNode_isCharLit (exprNode e)
9116 {
9117   if (exprNode_isDefined (e))
9118     {
9119       return (multiVal_isChar (exprNode_getValue (e)));
9120     }
9121   else
9122     {
9123       return FALSE;
9124     }
9125 }
9126
9127 bool
9128 exprNode_isNumLit (exprNode e)
9129 {
9130   if (exprNode_isDefined (e))
9131     {
9132       return (multiVal_isInt (exprNode_getValue (e)));
9133     }
9134   else
9135     {
9136       return FALSE;
9137     }
9138 }
9139
9140 static bool
9141 exprNode_isFalseConstant (exprNode e)
9142 {
9143   if (exprNode_isDefined (e))
9144     {
9145       cstring s = exprNode_rootVarName (e);
9146
9147       if (cstring_equal (s, context_getFalseName ()))
9148         {
9149           return TRUE;
9150         }
9151     }
9152
9153   return FALSE;
9154 }
9155
9156 bool
9157 exprNode_matchLiteral (ctype expected, exprNode e)
9158 {
9159   if (exprNode_isDefined (e))
9160     {
9161       multiVal m = exprNode_getValue (e);
9162       
9163       if (multiVal_isDefined (m))
9164         {
9165           if (multiVal_isInt (m))
9166             {
9167               long int val = multiVal_forceInt (m);
9168               
9169               if (ctype_isDirectBool (ctype_realishType (expected)))
9170                 {
9171                   if (val == 0) 
9172                     {
9173                       return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9174                     }
9175                   else 
9176                     {
9177                       return FALSE;
9178                     }
9179                 }
9180               
9181               if (ctype_isRealInt (expected))
9182                 {
9183                   /*
9184                   ** unsigned <- [ constant >= 0 is okay ]
9185                   */
9186                   
9187                   if (ctype_isUnsigned (expected))
9188                     {
9189                       if (val < 0)
9190                         {
9191                           return FALSE;
9192                         }
9193                     }
9194                   
9195                   /*
9196                   ** No checks on sizes of integers...maybe add
9197                   ** these later.
9198                   */
9199
9200                   DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9201                   DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9202                             bool_unparse (ctype_isInt (exprNode_getType (e)))));
9203
9204                   if (context_getFlag (FLG_NUMLITERAL) 
9205                       && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9206                     return TRUE;
9207                   } else {
9208                     if (val == 0) {
9209                       return TRUE;
9210                     } else {
9211                       return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9212                     }
9213                   }
9214                 }
9215               else if (ctype_isChar (expected))
9216                 {
9217                   return FALSE;
9218                 }
9219               else if (ctype_isArrayPtr (expected))
9220                 {
9221                   return (val == 0);
9222                 }
9223               else if (ctype_isAnyFloat (expected))
9224                 {
9225                   return (context_getFlag (FLG_NUMLITERAL));
9226                 }
9227               else
9228                 {
9229                   return FALSE;
9230                 }
9231             }
9232           else if (multiVal_isDouble (m))
9233             {
9234               if (ctype_isAnyFloat (expected))
9235                 {
9236                   return TRUE;
9237                 }
9238             }
9239           else if (multiVal_isChar (m))
9240             {
9241               char val = multiVal_forceChar (m);          
9242               
9243               if (ctype_isChar (expected))
9244                 {
9245                   if (ctype_isUnsigned (expected) && ((int)val) < 0)
9246                     {
9247                       return FALSE;
9248                     }
9249                   else
9250                     {
9251                       return TRUE;
9252                     }
9253                 }
9254             }
9255           else
9256             {
9257               return FALSE;
9258             }
9259         }
9260     }
9261   
9262   return FALSE;
9263 }
9264
9265 bool
9266 exprNode_matchType (ctype expected, exprNode e)
9267 {
9268   ctype actual;
9269   
9270   if (!exprNode_isDefined (e)) return TRUE;
9271
9272   actual = ctype_realishType (exprNode_getType (e));
9273
9274   if (ctype_match (ctype_realishType (expected), actual))
9275     {
9276       return TRUE;
9277     }
9278
9279   llassert (!exprNode_isError (e));
9280   return (exprNode_matchLiteral (expected, e));
9281 }
9282
9283 static bool
9284 exprNode_matchTypes (exprNode e1, exprNode e2)
9285 {
9286   ctype t1;
9287   ctype t2;
9288  
9289   if (!exprNode_isDefined (e1)) return TRUE;
9290   if (!exprNode_isDefined (e2)) return TRUE;
9291
9292   /*
9293   ** realish type --- keep bools, bools 
9294   */ 
9295
9296   t1 = ctype_realishType (exprNode_getType (e1));
9297   t2 = ctype_realishType (exprNode_getType (e2));
9298
9299   if (ctype_match (t1, t2)) 
9300     {
9301       return TRUE;
9302     }
9303
9304   return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9305 }
9306
9307 /*
9308 ** pass e as ct
9309 */
9310
9311 static bool
9312   exprNode_matchArgType (ctype ct, exprNode e)
9313 {
9314   ctype et;
9315
9316   if (!exprNode_isDefined (e))
9317     {
9318       return TRUE;
9319     }
9320
9321   et = ctype_realType (exprNode_getType (e));
9322
9323   if (ctype_matchArg (ct, et)) return TRUE;
9324   
9325   llassert (!exprNode_isError (e));
9326   return (exprNode_matchLiteral (ct, e));
9327 }
9328
9329 static /*@only@*/ exprNodeSList
9330   exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9331 {
9332   if (exprNode_isDefined (e))
9333     {
9334       if (e->kind == XPR_STMTLIST)
9335         {
9336           return (exprNodeSList_append
9337                   (exprNode_flatten (exprData_getPairA (e->edata)),
9338                    exprNode_flatten (exprData_getPairB (e->edata))));
9339         }
9340       else if (e->kind == XPR_BLOCK)
9341         {
9342           return (exprNode_flatten (exprData_getSingle (e->edata)));
9343         }
9344       else
9345         {
9346           return (exprNodeSList_singleton (e));
9347         }
9348     }
9349
9350   return exprNodeSList_new ();
9351 }
9352
9353 static /*@exposed@*/ exprNode
9354 exprNode_lastStatement (/*@returned@*/ exprNode e)
9355 {
9356   if (exprNode_isDefined (e))
9357     {
9358       if (e->kind == XPR_STMTLIST)
9359         {
9360           exprNode b = exprData_getPairB (e->edata);
9361
9362           if (exprNode_isDefined (b))
9363             {
9364               return exprNode_lastStatement (b);
9365             }
9366           else
9367             {
9368               return exprNode_lastStatement (exprData_getPairA (e->edata));
9369             }
9370         }
9371       else if (e->kind == XPR_BLOCK)
9372         {
9373           return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9374         }
9375       else
9376         {
9377           return (e);
9378         }
9379     }
9380
9381   return exprNode_undefined;
9382 }
9383
9384 static /*@exposed@*/ exprNode
9385 exprNode_firstStatement (/*@returned@*/ exprNode e)
9386 {
9387   if (exprNode_isDefined (e))
9388     {
9389       if (e->kind == XPR_STMTLIST)
9390         {
9391           exprNode b = exprData_getPairA (e->edata);
9392
9393           if (exprNode_isDefined (b))
9394             {
9395               return exprNode_firstStatement (b);
9396             }
9397           else
9398             {
9399               return exprNode_firstStatement (exprData_getPairB (e->edata));
9400             }
9401         }
9402       else if (e->kind == XPR_BLOCK)
9403         {
9404           return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9405         }
9406       else
9407         {
9408           return (e);
9409         }
9410     }
9411
9412   return exprNode_undefined;
9413 }
9414   
9415 static void
9416 exprNode_mergeUSs (exprNode res, exprNode other)
9417 {
9418   if (exprNode_isDefined (res) && exprNode_isDefined (other))
9419     {
9420       res->msets = sRefSet_union (res->msets, other->msets);
9421       res->sets = sRefSet_union (res->sets, other->sets);
9422       res->uses = sRefSet_union (res->uses, other->uses);
9423     }
9424 }
9425
9426 static void
9427 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9428 {
9429   if (exprNode_isDefined (res))
9430     {
9431       if (exprNode_isDefined (other1))
9432         {
9433           res->sets = sRefSet_union (res->sets, other1->sets);
9434           res->msets = sRefSet_union (res->msets, other1->msets);
9435           res->uses = sRefSet_union (res->uses, other1->uses);
9436         }
9437       if (exprNode_isDefined (other2))
9438         {
9439           res->sets = sRefSet_union (res->sets, other2->sets);
9440           res->msets = sRefSet_union (res->msets, other2->msets);
9441           res->uses = sRefSet_union (res->uses, other2->uses);
9442         }
9443     }
9444 }
9445
9446 /*
9447 ** modifies e->uses
9448 **
9449 ** Reports errors is s is not defined.
9450 */
9451
9452 static void
9453 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9454 {
9455   if (exprNode_isDefined (e))
9456     {
9457       e->uses = sRefSet_insert (e->uses, s);
9458     }
9459 }
9460   
9461 void
9462 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9463 {
9464   if (sRef_isKnown (s) && !sRef_isConst (s))
9465     {
9466       /*
9467       ** need to check all outer types are useable
9468       */
9469
9470       DPRINTF (("Check use: %s / %s",
9471                 exprNode_unparse (e), sRef_unparse (s)));
9472       
9473       exprNode_addUse (e, s);
9474      
9475       if (!context_inProtectVars ())
9476         {
9477           /*
9478           ** only report the deepest error
9479           */
9480           
9481           sRef errorRef = sRef_undefined;
9482           sRef lastRef  = sRef_undefined;
9483           bool deadRef = FALSE;
9484           bool unuseable = FALSE;
9485           bool errorMaybe = FALSE;
9486           
9487           while (sRef_isValid (s) && sRef_isKnown (s))
9488             {
9489               ynm readable = sRef_isReadable (s);
9490
9491               DPRINTF (("Readable: %s / %s",
9492                         sRef_unparseFull (s), ynm_unparse (readable)));
9493
9494               if (!(ynm_toBoolStrict (readable)))
9495                 {
9496                   if (ynm_isMaybe (readable))
9497                     {
9498                       lastRef = errorRef;
9499                       errorRef = s;
9500                       DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
9501                       deadRef = sRef_isPossiblyDead (errorRef);
9502                       unuseable = sRef_isUnuseable (errorRef);
9503                       errorMaybe = TRUE;
9504                     }
9505                   else
9506                     {
9507                       lastRef = errorRef;
9508                       errorRef = s;
9509                       deadRef = sRef_isDead (errorRef);
9510                       unuseable = sRef_isUnuseable (errorRef);
9511                       errorMaybe = FALSE;
9512                     }
9513
9514                   if (!sRef_isPartial (s))
9515                     {
9516                       DPRINTF (("Defining! %s", sRef_unparseFull (s)));
9517                       sRef_setDefined (s, fileloc_undefined);
9518                     }
9519                 }
9520
9521               s = sRef_getBaseSafe (s);
9522             } /* end while */
9523           
9524           if (sRef_isValid (errorRef)) 
9525             {
9526               if (sRef_isValid (lastRef) && sRef_isField (lastRef) 
9527                   && sRef_isPointer (errorRef))
9528                 {
9529                   errorRef = lastRef;
9530                 }
9531               
9532               if (deadRef)
9533                 {
9534                   if (sRef_isThroughArrayFetch (errorRef))
9535                     {
9536                       if (optgenerror 
9537                           (FLG_STRICTUSERELEASED,
9538                            message ("%q %q may be used after being released", 
9539                                     sRef_unparseKindNamePlain (errorRef),
9540                                     sRef_unparse (errorRef)),
9541                            loc))
9542                         {
9543                           sRef_showRefKilled (errorRef);
9544                           
9545                           if (sRef_isKept (errorRef))
9546                             {
9547                               sRef_clearAliasState (errorRef, loc);
9548                             }
9549                         }
9550                     }
9551                   else
9552                     {
9553                       DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9554
9555                       if (optgenerror
9556                           (FLG_USERELEASED,
9557                            message ("%q %q %qused after being released", 
9558                                     sRef_unparseKindNamePlain (errorRef),
9559                                     sRef_unparse (errorRef),
9560                                     cstring_makeLiteral (errorMaybe 
9561                                                          ? "may be " : "")),
9562                            loc))
9563                         {
9564                           sRef_showRefKilled (errorRef);
9565                           
9566                           if (sRef_isKept (errorRef))
9567                             {
9568                               sRef_clearAliasState (errorRef, loc);
9569                             }
9570                         }
9571                     }
9572                 }
9573               else if (unuseable)
9574                 {
9575                   if (optgenerror
9576                       (FLG_USEDEF,
9577                        message ("%q %q%qused in inconsistent state", 
9578                                 sRef_unparseKindName (errorRef),
9579                                 sRef_unparseOpt (errorRef),
9580                                 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9581                        loc))
9582                     {
9583                       sRef_showStateInconsistent (errorRef);
9584                     }
9585                 }
9586               else
9587                 {
9588                   DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
9589
9590                   voptgenerror 
9591                     (FLG_USEDEF,
9592                      message ("%q %q%qused before definition", 
9593                               sRef_unparseKindName (errorRef),
9594                               sRef_unparseOpt (errorRef),
9595                               cstring_makeLiteral (errorMaybe ? "may be " : "")),
9596                      loc);
9597
9598                   DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
9599                 }
9600               
9601               sRef_setDefined (errorRef, loc);
9602           
9603               if (sRef_isAddress (errorRef))
9604                 {
9605                   sRef_setDefined (sRef_getRootBase (errorRef), loc);
9606                 }
9607             } /* end is error */
9608         }
9609     }
9610
9611   setCodePoint ();
9612 }
9613
9614 static void
9615 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
9616 {
9617   if (exprNode_isDefined (e) && sRef_isKnown (s))
9618     {
9619       e->uses = sRefSet_insert (e->uses, s);
9620     }
9621 }
9622
9623 static void
9624 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9625 {
9626   if (exprNode_isDefined (e))
9627     {
9628       e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9629     }
9630 }
9631
9632 void
9633 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
9634 {
9635   sRef defines = sRef_undefined;
9636
9637   if (sRef_isValid (s) && !sRef_isNothing (s))
9638     {
9639       uentry ue = sRef_getBaseUentry (s);
9640
9641       if (uentry_isValid (ue))
9642         {
9643           uentry_setLset (ue);
9644         }
9645
9646       if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9647         {
9648           voptgenerror (FLG_USEDEF,
9649                         message ("Attempt to set unuseable storage: %q", 
9650                                  sRef_unparse (s)),
9651                         exprNode_loc (e));
9652         }
9653      
9654       if (sRef_isMeaningful (s))
9655         {
9656           
9657           if (sRef_isDead (s))
9658             {
9659               sRef base = sRef_getBaseSafe (s);
9660
9661               if (sRef_isValid (base) 
9662                   && sRef_isDead (base))
9663                 {
9664                   sRef_setPartial (s, exprNode_loc (e));
9665                 }
9666               
9667               defines = s; /* okay - modifies for only param */
9668             }
9669           else if (sRef_isPartial (s))
9670             {
9671               sRef eref = exprNode_getSref (e);
9672
9673               if (!sRef_isPartial (eref))
9674                 {
9675                   /*
9676                   ** should do something different here???
9677                   */
9678                   
9679                   sRef_setDefinedComplete (eref, exprNode_loc (e));               
9680                 }
9681               else
9682                 {
9683                   sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9684                 }
9685
9686               if (sRef_isMeaningful (eref))
9687                 {
9688                   defines = eref;
9689                 }
9690               else
9691                 {                
9692                   defines = s;
9693                 }
9694             }
9695           else if (sRef_isAllocated (s))
9696             {
9697               sRef eref = exprNode_getSref (e);
9698
9699               
9700               if (!sRef_isAllocated (eref))
9701                 {
9702                   sRef_setDefinedComplete (eref, exprNode_loc (e));
9703                 }
9704               else
9705                 {
9706                   sRef base = sRef_getBaseSafe (eref);
9707                   
9708                   if (sRef_isValid (base))
9709                     {
9710                       sRef_setPdefined (base, exprNode_loc (e)); 
9711                     }
9712                 }
9713
9714               defines = s;
9715             }
9716           else 
9717             {
9718               sRef_setDefinedNCComplete (s, exprNode_loc (e));
9719               defines = s;
9720             }
9721
9722         }
9723       else /* not meaningful...but still need to insert it */
9724         {
9725           defines = s;
9726         }
9727     }
9728
9729   if (exprNode_isDefined (e) && sRef_isValid (defines))
9730     {
9731       e->sets = sRefSet_insert (e->sets, defines); 
9732     }
9733 }
9734
9735 void
9736 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
9737 {
9738   if (sRef_isValid (s) && !sRef_isNothing (s))
9739     {
9740       uentry ue = sRef_getBaseUentry (s);
9741
9742       if (uentry_isValid (ue))
9743         {
9744           uentry_setLset (ue);
9745         }
9746
9747       if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9748         {
9749           voptgenerror (FLG_USEDEF,
9750                         message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9751                         exprNode_loc (e));
9752         }
9753       
9754       if (sRef_isMeaningful (s))
9755         {
9756           sRef_setDefinedComplete (s, exprNode_loc (e));
9757         }
9758       
9759       if (exprNode_isDefined (e))
9760         {
9761           e->msets = sRefSet_insert (e->msets, s);
9762         }
9763     }
9764 }
9765
9766 static void
9767 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9768 {
9769   checkAnyCall (fcn, cstring_undefined, params, args, 
9770                 FALSE, sRefSet_undefined, FALSE, 0);
9771 }
9772
9773 static void
9774 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current, 
9775              /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9776 {
9777   setCodePoint ();
9778   
9779   if (uentry_isYield (ucurrent))
9780     {
9781       sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9782       exprNode_checkSet (current, current->sref);
9783     }
9784   else 
9785     {
9786       if (uentry_isSefParam (ucurrent))
9787         {
9788           sRefSet sets = current->sets;
9789           sRef ref = exprNode_getSref (current);
9790
9791           if (sRef_isMacroParamRef (ref))
9792             {
9793               uentry ue = sRef_getUentry (ref);
9794
9795               if (!uentry_isSefParam (ue))
9796                 {
9797                   voptgenerror 
9798                     (FLG_SEFPARAMS,
9799                      message
9800                      ("Parameter %d to %s is declared sef, but "
9801                       "the argument is a macro parameter declared "
9802                       "without sef: %s",
9803                       argno, exprNode_unparse (fcn),
9804                       exprNode_unparse (current)),
9805                      exprNode_loc (current));
9806                 }
9807             }
9808
9809           if (!sRefSet_isEmpty (sets))
9810             {
9811               sRefSet reported = sRefSet_undefined;
9812               
9813               sRefSet_realElements (current->sets, el)
9814                 {
9815                   if (sRefSet_isSameNameMember (reported, el))
9816                     {
9817                       ; /* don't report again */
9818                     }
9819                   else
9820                     {
9821                       if (sRef_isUnconstrained (el))
9822                         {
9823                           voptgenerror 
9824                             (FLG_SEFUNSPEC,
9825                              message
9826                              ("Parameter %d to %s is declared sef, but "
9827                               "the argument calls unconstrained function %s "
9828                               "(no guarantee it will not modify something): %s",
9829                               argno, exprNode_unparse (fcn),
9830                               sRef_unconstrainedName (el),
9831                               exprNode_unparse (current)),
9832                              exprNode_loc (current));
9833                         }
9834                       else
9835                         {
9836                           voptgenerror 
9837                             (FLG_SEFPARAMS,
9838                              message
9839                              ("Parameter %d to %s is declared sef, but "
9840                               "the argument may modify %q: %s",
9841                               argno, exprNode_unparse (fcn),
9842                               sRef_unparse (el),
9843                               exprNode_unparse (current)),
9844                              exprNode_loc (current));
9845                         }
9846                     } 
9847                 } end_sRefSet_realElements;
9848             }
9849         }
9850       
9851       checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9852       exprNode_mergeUSs (fcn, current);
9853     }
9854 }
9855
9856 static void
9857   checkAnyCall (/*@dependent@*/ exprNode fcn, 
9858                 /*@dependent@*/ cstring fname,
9859                 uentryList pn, 
9860                 exprNodeList args, 
9861                 bool hasMods, sRefSet mods,
9862                 bool isSpec,
9863                 int specialArgs)
9864 {
9865   int paramno = 0;
9866   int nargs = exprNodeList_size (args);
9867
9868   setCodePoint ();
9869
9870   /*
9871   ** concat all args ud's to f, add each arg sref as a use unless
9872   ** it was specified as "out", in which case it is a def.
9873   */
9874   
9875   uentryList_reset (pn);
9876   
9877   /*
9878   ** aliasing checks:
9879   **
9880   **    if paramn is only or unique, no other arg may alias argn
9881   */
9882   
9883   exprNodeList_elements (args, current) 
9884     {
9885       paramno++;
9886       
9887       if (exprNode_isDefined (current)) 
9888         {
9889           if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn))) 
9890             {
9891               uentry ucurrent = uentryList_current (pn);
9892               
9893               if (specialArgs == 0 
9894                   || (paramno < specialArgs))
9895                 {
9896                   checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
9897
9898                   if (context_maybeSet (FLG_ALIASUNIQUE))
9899                     {
9900                       if (uentry_isOnly (ucurrent)
9901                           || uentry_isUnique (ucurrent))
9902                         {
9903                           checkUniqueParams (fcn, current, args,
9904                                              paramno, ucurrent);
9905                         }
9906                     }
9907                 } 
9908             }
9909           else /* uentry is undefined */
9910             {
9911               if (specialArgs == 0)
9912                 {
9913                   exprNode_checkUseParam (current);
9914                 }
9915
9916               exprNode_mergeUSs (fcn, current);
9917             }   
9918         }
9919       uentryList_advanceSafe (pn);
9920     } end_exprNodeList_elements;
9921   
9922   if (hasMods)
9923     {
9924       setCodePoint ();
9925
9926       sRefSet_allElements (mods, s)
9927         {
9928           sRef fb;
9929           sRef rb = sRef_getRootBase (s);
9930           
9931           if (sRef_isFileOrGlobalScope (rb))
9932             {
9933               context_usedGlobal (rb);
9934             }
9935           
9936           fb = sRef_fixBaseParam (s, args);
9937           
9938           if (!sRef_isMacroParamRef (fb))
9939             {
9940               if (sRef_isNothing (fb))
9941                 {
9942                   ;
9943                 }
9944               else
9945                 {
9946                   if (sRef_isValid (fb))
9947                     {
9948                       uentry ue = sRef_getBaseUentry (s);
9949                       
9950                       if (uentry_isValid (ue))
9951                         {
9952                           uentry_setLset (ue);
9953                         }
9954                     }
9955                   
9956                   fcn->sets = sRefSet_insert (fcn->sets, fb);
9957                 }
9958             }
9959           sRef_clearDerivedComplete (s); 
9960         } end_sRefSet_allElements;
9961       
9962       setCodePoint ();
9963     }
9964   else
9965     {
9966       if (context_hasMods ())
9967         {
9968           if (context_maybeSet (FLG_MODUNCON))
9969             {
9970               voptgenerror
9971                 (FLG_MODUNCON,
9972                  message ("Undetected modification possible "
9973                           "from call to unconstrained function %s: %s", 
9974                           fname,
9975                           exprNode_unparse (fcn)),
9976                  exprNode_loc (fcn));
9977             }
9978         }
9979       else
9980         {
9981           if (context_maybeSet (FLG_MODUNCONNOMODS)
9982               && !(context_inIterDef () || context_inIterEnd ()))
9983             {
9984               voptgenerror
9985                 (FLG_MODUNCONNOMODS,
9986                  message ("Undetected modification possible "
9987                           "from call to unconstrained function %s: %s", 
9988                           fname,
9989                           exprNode_unparse (fcn)),
9990                  exprNode_loc (fcn));
9991             }
9992         }
9993
9994       exprNode_checkSetAny (fcn, fname);
9995     }
9996 }
9997
9998 void exprNode_checkUseParam (exprNode current)
9999 {
10000   if (exprNode_isDefined (current))
10001     {
10002       exprNode_checkUse (current, current->sref, current->loc);
10003     }
10004 }
10005
10006 static ctype
10007   checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10008                  /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10009                  lltok op)
10010 {
10011   ctype ret = tr1;
10012   
10013   if (!ctype_match (tr1, tr2))
10014     {
10015       if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10016           (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10017         {
10018           ;
10019         }
10020       else
10021         {
10022           (void) gentypeerror 
10023             (tr1, e1, tr2, e2,
10024              message ("Incompatible types for %s (%s, %s): %s %s %s",
10025                       lltok_unparse (op),
10026                       ctype_unparse (te1),
10027                       ctype_unparse (te2),
10028                       exprNode_unparse (e1), lltok_unparse (op), 
10029                       exprNode_unparse (e2)),
10030              e1->loc);
10031         }
10032       ret = ctype_unknown;
10033     }
10034   else
10035     {
10036       if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10037         {
10038           ret = ctype_resolveNumerics (tr1, tr2);
10039         }
10040       else if (!context_msgStrictOps ()) 
10041         {
10042                   if (ctype_isPointer (tr1))
10043             {
10044               if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10045                 {
10046                   ret = ctype_int;
10047                 }
10048               else if (ctype_isInt (tr2))
10049                 {
10050                   ret = te1;
10051                 }
10052               else
10053                 {
10054                   ret = ctype_unknown;
10055                 }
10056             }
10057           else if (ctype_isPointer (tr2))
10058             {
10059               if (ctype_isPointer (tr1))
10060                 {
10061                   ret = ctype_int;
10062                 }
10063               else if (ctype_isInt (tr1))
10064                 {
10065                   ret = te2;
10066                 }
10067               else
10068                 {
10069                   ret = ctype_unknown; 
10070                 }
10071             }
10072           else
10073             {
10074               ret = ctype_resolveNumerics (tr1, tr2);
10075             }
10076         }
10077       else
10078         {
10079           int opid = lltok_getTok (op);
10080           bool comparop = (opid == EQ_OP || opid == NE_OP 
10081                            || opid == TLT || opid == TGT
10082                            || opid == LE_OP || opid == GE_OP);
10083           
10084           if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10085             {
10086               if (comparop
10087                   && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10088                       || (ctype_isBool (tr1) && ctype_isBool (tr2))
10089                       || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10090                 {
10091                   ; /* no error */
10092                 }
10093               else
10094                 {
10095                   if (ctype_sameName (te1, te2))
10096                     {
10097                       voptgenerror
10098                         (FLG_STRICTOPS,
10099                          message ("Operands of %s are non-numeric (%t): %s %s %s",
10100                                   lltok_unparse (op), te1, 
10101                                   exprNode_unparse (e1), lltok_unparse (op), 
10102                                   exprNode_unparse (e2)),
10103                          e1->loc);
10104                     }
10105                   else
10106                     {
10107                       voptgenerror
10108                         (FLG_STRICTOPS,
10109                          message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10110                                   lltok_unparse (op), te1, te2, 
10111                                   exprNode_unparse (e1), lltok_unparse (op),
10112                                   exprNode_unparse (e2)),
10113                          e1->loc);
10114                     }
10115                 }
10116             }
10117           else if (!ctype_isNumeric (tr1))
10118             {
10119               voptgenerror
10120                 (FLG_STRICTOPS,
10121                  message ("Right operand of %s is non-numeric (%t): %s %s %s",
10122                           lltok_unparse (op), te1, 
10123                           exprNode_unparse (e1), lltok_unparse (op), 
10124                           exprNode_unparse (e2)),
10125                  e1->loc);
10126             }
10127           else 
10128             {
10129               if (!ctype_isNumeric (tr2))
10130                 {
10131                   voptgenerror
10132                     (FLG_STRICTOPS,
10133                      message ("Left operand of %s is non-numeric (%t): %s %s %s",
10134                               lltok_unparse (op), te2, 
10135                               exprNode_unparse (e1), lltok_unparse (op), 
10136                               exprNode_unparse (e2)),
10137                      e2->loc);
10138                 }
10139             }
10140           
10141           ret = ctype_unknown;
10142         }
10143     }
10144
10145   return ret;
10146 }
10147
10148 static void
10149 abstractOpError (ctype tr1, ctype tr2, lltok op, 
10150                  /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, 
10151                  fileloc loc1, fileloc loc2)
10152 {
10153   if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10154     {
10155       if (ctype_match (tr1, tr2))
10156         {
10157           voptgenerror
10158             (FLG_ABSTRACT,
10159              message ("Operands of %s are abstract type (%t): %s %s %s",
10160                       lltok_unparse (op), tr1, 
10161                       exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10162              loc1);
10163         }
10164       else
10165         {
10166           voptgenerror 
10167             (FLG_ABSTRACT,
10168              message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10169                       lltok_unparse (op), tr1, tr2, 
10170                       exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10171              loc1);
10172         }
10173     }
10174   else if (ctype_isRealAbstract (tr1))
10175     {
10176       voptgenerror
10177         (FLG_ABSTRACT,
10178          message ("Left operand of %s is abstract type (%t): %s %s %s",
10179                   lltok_unparse (op), tr1, 
10180                   exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10181          loc1);
10182     }
10183   else 
10184     {
10185       if (ctype_isRealAbstract (tr2))
10186         {
10187           voptgenerror
10188             (FLG_ABSTRACT,
10189              message ("Right operand of %s is abstract type (%t): %s %s %s",
10190                       lltok_unparse (op), tr2, 
10191                       exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10192              loc2);
10193         }
10194     }
10195 }
10196
10197 /*
10198 ** e1 <= e2
10199 **
10200 ** requies e1 and e2 and not error exprNode's.
10201 **
10202 ** Checks:
10203 **
10204 **    If e1 is a component of an abstract type, and e2 is mutable and client-visible, 
10205 **    the rep of the abstract type is exposed.
10206 **
10207 ** The order is very important:
10208 **
10209 **    check rep expose (move into check transfer)
10210 **    check transfer
10211 **    setup aliases
10212 */
10213
10214 /*
10215 ** This isn't really a sensible procedure, but the indententation
10216 ** was getting too deep.
10217 */
10218
10219 static void
10220 checkOneRepExpose (sRef ysr, sRef base, 
10221                    /*@notnull@*/ exprNode e1, 
10222                    /*@notnull@*/ exprNode e2, ctype ct,
10223                    sRef s2b)
10224 {
10225   if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr) 
10226         || sRef_isOwned (ysr) 
10227         || sRef_isExposed (ysr)))
10228     {
10229       if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10230           && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10231
10232         {
10233           if (sRef_isIReference (ysr))
10234             {
10235               if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10236                 {
10237                   voptgenerror 
10238                     (FLG_ASSIGNEXPOSE,
10239                      message
10240                      ("Assignment of mutable component of parameter %q "
10241                       "to component of abstract "
10242                       "type %s exposes rep: %s = %s",
10243                       sRef_unparse (base),
10244                       ctype_unparse (ct),
10245                       exprNode_unparse (e1), exprNode_unparse (e2)),
10246                      e1->loc);
10247                 }
10248               else
10249                 {
10250                   voptgenerror 
10251                     (FLG_ASSIGNEXPOSE,
10252                      message
10253                      ("Assignment of mutable component of parameter %q "
10254                       "(through alias %q) to component of abstract "
10255                       "type %s exposes rep: %s = %s",
10256                       sRef_unparse (base),
10257                       sRef_unparse (e2->sref),
10258                       ctype_unparse (ct),
10259                       exprNode_unparse (e1), exprNode_unparse (e2)),
10260                      e1->loc);
10261                 }
10262             }
10263           else
10264             {
10265               if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10266                 {
10267                   voptgenerror 
10268                     (FLG_ASSIGNEXPOSE,
10269                      message ("Assignment of mutable parameter %q "
10270                               "to component of abstract type %s "
10271                               "exposes rep: %s = %s",
10272                               sRef_unparse (base),
10273                               ctype_unparse (ct),
10274                               exprNode_unparse (e1), 
10275                               exprNode_unparse (e2)),
10276                      e1->loc);
10277                 }
10278               else
10279                 {
10280                   voptgenerror 
10281                     (FLG_ASSIGNEXPOSE,
10282                      message ("Assignment of mutable parameter %q "
10283                               "(through alias %q) to "
10284                               "component of abstract type %s exposes "
10285                               "rep: %s = %s",
10286                               sRef_unparse (base),
10287                               sRef_unparse (e2->sref),
10288                               ctype_unparse (ct),
10289                               exprNode_unparse (e1), 
10290                               exprNode_unparse (e2)),
10291                      e1->loc);
10292                 }
10293             }
10294         }
10295       
10296       if (sRef_isFileOrGlobalScope (s2b))
10297         {
10298           if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10299             {
10300               voptgenerror 
10301                 (FLG_REPEXPOSE,
10302                  message ("Assignment of global %q "
10303                           "to component of "
10304                           "abstract type %s exposes rep: %s = %s",
10305                           sRef_unparse (base),
10306                           ctype_unparse (ct),
10307                           exprNode_unparse (e1), exprNode_unparse (e2)),
10308                  e1->loc);
10309             }
10310           else
10311             {
10312               voptgenerror 
10313                 (FLG_REPEXPOSE,
10314                  message ("Assignment of global %q (through alias %q) "
10315                           "to component of "
10316                           "abstract type %s exposes rep: %s = %s",
10317                           sRef_unparse (base),
10318                           sRef_unparse (e2->sref),
10319                           ctype_unparse (ct),
10320                           exprNode_unparse (e1), exprNode_unparse (e2)),
10321                  e1->loc);
10322             }
10323         }
10324     }
10325 }
10326
10327 static void
10328 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10329 {
10330   if (ctype_isRealFunction (exprNode_getType (e1))
10331       && !ctype_isRealPointer (exprNode_getType (e1)))
10332     {
10333       voptgenerror 
10334         (FLG_TYPE,
10335          message ("Invalid left-hand side of assignment (function type %s): %s",
10336                   ctype_unparse (exprNode_getType (e1)),
10337                   exprNode_unparse (e1)),
10338          e1->loc);
10339     }
10340
10341   if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10342     {
10343       ctype t2 = exprNode_getType (e2);
10344       sRef sr = sRef_getRootBase (e1->sref);
10345       ctype ct = sRef_getType (sr);
10346
10347       if (ctype_isAbstract (t2) 
10348           && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10349         {
10350           /* it is immutable, okay to reference */
10351           goto donerepexpose;
10352         }
10353
10354       if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10355         {
10356           sRef s2b = sRef_getRootBase (e2->sref);
10357           sRef s1 = e1->sref;
10358           sRef s1b = sRef_getRootBase (s1);
10359           sRefSet aliases;
10360
10361           aliases = usymtab_canAlias (e2->sref);
10362           
10363           if (!sRef_similar (s2b, s1b) 
10364               && !sRef_isExposed (s1)
10365               && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10366             {
10367               if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b) 
10368                   && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10369                   && !sRef_isExposed (s2b))
10370                 {
10371                   if (sRef_isIReference (e2->sref))
10372                     {
10373                       voptgenerror 
10374                         (FLG_ASSIGNEXPOSE,
10375                          message 
10376                          ("Assignment of mutable component of parameter %q "
10377                           "to component of abstract type %s exposes rep: %s = %s",
10378                           sRef_unparse (s2b),
10379                           ctype_unparse (ct),
10380                           exprNode_unparse (e1), exprNode_unparse (e2)),
10381                          e1->loc);
10382                     }
10383                   else
10384                     {
10385                       voptgenerror 
10386                         (FLG_ASSIGNEXPOSE,
10387                          message ("Assignment of mutable parameter %q to "
10388                                   "component of abstract type %s exposes rep: %s = %s",
10389                                   sRef_unparse (s2b),
10390                                   ctype_unparse (ct),
10391                                   exprNode_unparse (e1), exprNode_unparse (e2)),
10392                          e1->loc);
10393                     }
10394                 }
10395
10396               if (sRef_isFileOrGlobalScope (s2b))
10397                 {
10398                   voptgenerror
10399                     (FLG_ASSIGNEXPOSE,
10400                      message ("Assignment of global %q to component of "
10401                               "abstract type %s exposes rep: %s = %s",
10402                               sRef_unparse (s2b),
10403                               ctype_unparse (ct),
10404                               exprNode_unparse (e1), exprNode_unparse (e2)),
10405                      e1->loc);
10406                 }
10407               
10408               sRefSet_realElements (aliases, ysr)
10409                 {
10410                   sRef base = sRef_getRootBase (ysr);
10411                   
10412                   if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10413                       || sRef_sameName (base, s1b))
10414                     {
10415                      ; /* error already reported or same sref */
10416                     }
10417                   else
10418                     {
10419                       checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10420                     }
10421                 } end_sRefSet_realElements;
10422             }
10423           sRefSet_free (aliases);
10424         }
10425     }
10426
10427  donerepexpose:
10428
10429   /*
10430   ** function variables don't really work...
10431   */
10432
10433   if (!ctype_isFunction (ctype_realType (e2->typ)))
10434     {
10435       if (isInit)
10436         {
10437             DPRINTF (("Check init: %s / %s",
10438                       exprNode_unparse (e1), exprNode_unparse (e2)));
10439           checkInitTransfer (e1, e2); 
10440         }
10441       else
10442         {
10443           checkAssignTransfer (e1, e2); 
10444         }
10445     }
10446   else
10447     {
10448       sRef fref = e2->sref;
10449
10450       sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10451       sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10452
10453             /* Need to typecheck the annotation on the parameters */
10454       
10455       if (ctype_isRealFunction (e1->typ)) {
10456         uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10457         uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10458
10459         if (!uentryList_isMissingParams (e1p)
10460             && !uentryList_isMissingParams (e2p)
10461             && uentryList_size (e1p) > 0) {
10462           if (uentryList_size (e1p) == uentryList_size (e2p)) {
10463             int n = 0;
10464             
10465             uentryList_elements (e1p, el1) {
10466               uentry el2;
10467
10468               el2 = uentryList_getN (e2p, n);
10469               n++;
10470               uentry_checkMatchParam (el1, el2, n, e2);
10471             } end_uentryList_elements;
10472           }
10473         }
10474       }
10475     }
10476
10477   if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10478     {
10479        ;
10480     }
10481   else
10482     {
10483       DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10484       updateAliases (e1, e2); 
10485     }
10486 }
10487
10488 static void 
10489 checkMacroParen (exprNode e)
10490 {
10491   if (exprNode_isError (e) || e->kind == XPR_CAST)
10492     {
10493      ;
10494     }
10495   else 
10496     {
10497       if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10498         {
10499           voptgenerror 
10500             (FLG_MACROPARENS,
10501              message ("Macro parameter used without parentheses: %s", 
10502                       exprNode_unparse (e)),
10503              e->loc);
10504         }
10505     }
10506 }
10507
10508 static void
10509 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10510 {
10511   if (isnull)
10512     {
10513       e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10514     }
10515   else
10516     {
10517       e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10518     }
10519 }
10520
10521 /*
10522 ** e1 <= e2
10523 **
10524 ** if e2 is a parameter or global derived location which
10525 ** can be modified (that is, e2 is a mutable abstract type,
10526 ** or a derived pointer), then e1 can alias e2.
10527 **
10528 ** e1 can alias everything which e2 can alias.
10529 **
10530 ** Also, if e1 is guarded, remove from guard sets!
10531 */
10532
10533 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10534 {
10535   if (!context_inProtectVars ())
10536     {
10537       /*
10538       ** depends on types of e1 and e2
10539       */
10540       
10541       sRef s1 = e1->sref;
10542       sRef s2 = e2->sref;
10543       ctype t1 = exprNode_getType (e1);
10544       
10545       /* handle pointer sRefs, record fields, arrays, etc... */
10546       
10547       if (!ctype_isRealSU (t1))
10548         {
10549           DPRINTF (("Copying real! %s", ctype_unparse (t1)));
10550           sRef_copyRealDerivedComplete (s1, s2);
10551         }
10552       else
10553         {
10554           /*
10555           ** Fields should alias
10556           */
10557
10558           DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10559         }
10560
10561       if (ctype_isMutable (t1) && sRef_isKnown (s1))
10562         {
10563           usymtab_clearAlias (s1);
10564           usymtab_addMustAlias (s1, s2); 
10565           DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10566         }
10567       else
10568         {
10569           DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
10570         }
10571
10572       if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10573         {
10574           usymtab_unguard (s1);
10575         }
10576     }
10577 }
10578
10579 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10580 {
10581   if (exprNode_isDefined (e))
10582     {
10583       e->loc = fileloc_update (e->loc, loc);
10584     }
10585   else
10586     {
10587       e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10588     }
10589
10590   return (e);
10591 }
10592
10593 static void checkUniqueParams (exprNode fcn,
10594                                /*@notnull@*/ exprNode current, 
10595                                exprNodeList args, 
10596                                int paramno, uentry ucurrent)
10597 {
10598   int iparamno = 0;
10599   sRef thisref = exprNode_getSref (current);
10600   
10601   /*
10602   ** Check if any argument could match this argument.
10603   */
10604   
10605   exprNodeList_elements (args, icurrent) 
10606     {
10607       iparamno++;
10608       
10609       if (iparamno != paramno)
10610         {
10611           sRef sr = exprNode_getSref (icurrent);
10612           
10613           if (sRef_similarRelaxed (thisref, sr))
10614             {
10615               if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10616                 {
10617                   voptgenerror 
10618                     (FLG_ALIASUNIQUE,
10619                      message
10620                      ("Parameter %d (%s) to function %s is declared %s but "
10621                       "is aliased by parameter %d (%s)",
10622                       paramno, 
10623                       exprNode_unparse (current),
10624                       exprNode_unparse (fcn),
10625                       alkind_unparse (uentry_getAliasKind (ucurrent)),
10626                       iparamno, exprNode_unparse (icurrent)),
10627                      current->loc);
10628                 }
10629             }
10630           else
10631             {
10632               sRefSet aliases = usymtab_canAlias (sr);
10633
10634               sRefSet_allElements (aliases, asr)
10635                 {
10636                   if (ctype_isUnknown (sRef_getType (thisref)))
10637                     {
10638                       sRef_setType (thisref, uentry_getType (ucurrent));
10639                     }
10640                   
10641                   if (sRef_similarRelaxed (thisref, asr)) 
10642                     {
10643                       if (sRef_isExternal (asr))  
10644                         {
10645                           if (sRef_isLocalState (thisref))
10646                             {
10647                               ; /* okay */
10648                             }
10649                           else
10650                             {
10651                               sRef base = sRef_getRootBase (asr);
10652                               
10653                               if (!sRef_similar (sRef_getBase (asr), thisref)) 
10654                                 {
10655                                   if (sRef_isUnique (base) || sRef_isOnly (base)
10656                                       || sRef_isKept (base)
10657                                       || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10658                                       || (sRef_isAddress (thisref) 
10659                                           && sRef_isLocalVar (sRef_getRootBase (thisref))))
10660                                     {
10661                                       ; /* okay, no error */
10662                                     }
10663                                   else
10664                                     {
10665                                       voptgenerror 
10666                                         (FLG_MAYALIASUNIQUE,
10667                                          message
10668                                          ("Parameter %d (%s) to function %s is declared %s but "
10669                                           "may be aliased externally by parameter %d (%s)",
10670                                           paramno, 
10671                                           exprNode_unparse (current),
10672                                           exprNode_unparse (fcn),
10673                                           alkind_unparse (uentry_getAliasKind (ucurrent)),
10674                                           iparamno, exprNode_unparse (icurrent)),
10675                                          current->loc);
10676                                     }
10677                                 }
10678                             }
10679                         }
10680                       else
10681                         {
10682                           voptgenerror 
10683                             (FLG_ALIASUNIQUE,
10684                              message
10685                              ("Parameter %d (%s) to function %s is declared %s but "
10686                               "is aliased externally by parameter %d (%s) through "
10687                               "alias %q",
10688                               paramno, 
10689                               exprNode_unparse (current),
10690                               exprNode_unparse (fcn),
10691                               alkind_unparse (uentry_getAliasKind (ucurrent)),
10692                               iparamno, exprNode_unparse (icurrent),
10693                               sRef_unparse (asr)),
10694                              current->loc);
10695                         }
10696                     }
10697                 } end_sRefSet_allElements;
10698               sRefSet_free (aliases);
10699             }
10700         }
10701     } end_exprNodeList_elements;
10702 }
10703
10704 long exprNode_getLongValue (exprNode e) {
10705   long value;
10706
10707   if (exprNode_hasValue (e) 
10708       && multiVal_isInt (exprNode_getValue (e)))
10709     {
10710       value = multiVal_forceInt (exprNode_getValue (e));
10711     }
10712   else
10713     {
10714       value = 0;
10715     }
10716   
10717   return value;
10718 }
10719
10720 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
10721 {
10722   if (exprNode_isDefined (p_e) )
10723     return ( p_e->loc );
10724   else
10725     return fileloc_undefined;
10726 }
10727
10728 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
10729 {
10730   /*
10731   ** Returns the location of the sequence point following e.
10732   **
10733   ** Only works for statements (for now).
10734   */
10735
10736   if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10737     lltok t = exprData_getUopTok (e->edata);
10738     return fileloc_copy(lltok_getLoc (t));
10739   } else {
10740     /* drl possible problem : warning fix
10741        llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
10742     */
10743     return fileloc_undefined;
10744   }
10745  }
10746
10747 exprNode exprNode_createNew(ctype c)
10748 {
10749   exprNode ret;
10750
10751   ret = exprNode_createPlain (c);
10752
10753   return ret;
10754 }
10755
10756 bool exprNode_isInitBlock (exprNode e)
10757 {
10758   return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);
10759 }
This page took 0.894114 seconds and 3 git commands to generate.