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