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