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