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