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