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