]> andersk Git - splint.git/blob - src/exprNode.c
Fixes for 3.0.0.18:
[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   return FALSE;
6360 }
6361
6362 bool
6363 exprNode_mustEscape (exprNode e)
6364 {
6365   if (exprNode_isDefined (e))
6366     {
6367       return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6368     }
6369
6370   return FALSE;
6371 }
6372
6373 bool
6374 exprNode_errorEscape (exprNode e)
6375 {
6376   if (exprNode_isDefined (e))
6377     {
6378       return exitkind_isError (e->exitCode);
6379     }
6380
6381   return FALSE;
6382 }
6383
6384 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6385 {
6386   exprNode ret = exprNode_createPartialCopy (e1);
6387
6388   DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6389
6390   ret->edata = exprData_makePair (e1, e2);
6391   ret->kind = XPR_STMTLIST;
6392
6393   if (exprNode_isDefined (e1))
6394     {
6395       ret->isJumpPoint = e1->isJumpPoint;
6396       ret->canBreak = e1->canBreak;
6397     }
6398   else
6399     {
6400       if (exprNode_isDefined (e2))
6401         {
6402           ret->loc = fileloc_update (ret->loc, e2->loc);
6403         }
6404     }
6405
6406   if (exprNode_isDefined (e2))
6407     {
6408       ret->exitCode = e2->exitCode;
6409       ret->mustBreak = e2->mustBreak;
6410       if (e2->canBreak) ret->canBreak = TRUE;
6411     }
6412
6413   /* 
6414   ** if e1 must return, then e2 is unreachable!
6415   */
6416
6417   if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6418     {
6419       if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1)) 
6420           && !(e2->isJumpPoint))
6421         {
6422           if (context_getFlag (FLG_UNREACHABLE))
6423             {
6424               exprNode nr = e2;
6425
6426               if (e2->kind == XPR_STMT)
6427                 {
6428                   nr = exprData_getUopNode (e2->edata);
6429                 }
6430
6431               if ((nr->kind == XPR_TOK 
6432                    && lltok_isSemi (exprData_getTok (nr->edata))))
6433                 {
6434                   /* okay to have unreachable ";" */
6435                   ret->exitCode = XK_MUSTEXIT;
6436                   ret->canBreak = TRUE;
6437                 }
6438               else
6439                 {
6440                   if (optgenerror (FLG_UNREACHABLE,
6441                                    message ("Unreachable code: %s", 
6442                                             exprNode_unparseFirst (nr)),
6443                                    exprNode_loc (nr)))
6444                     {
6445                       ret->isJumpPoint = TRUE;                
6446                       ret->mustBreak = FALSE;
6447                       ret->exitCode = XK_ERROR;
6448                       DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6449                     }
6450                   else
6451                     {
6452                       ret->exitCode = XK_MUSTEXIT;
6453                       ret->canBreak = TRUE;
6454                     }
6455
6456                 }
6457             }
6458         }
6459       else
6460         {
6461           if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6462             {
6463               /*
6464               ** We want a warning anytime we have:
6465               **         case xxx: ...  
6466               **                   yyy;  <<<- no break or return
6467               **         case zzz: ...
6468               */
6469               
6470               exprNode lastStmt = exprNode_lastStatement (e1);
6471               
6472               if (exprNode_isDefined (lastStmt) 
6473                   && !exprNode_mustEscape (lastStmt)
6474                   && !exprNode_mustBreak (lastStmt)
6475                   && !exprNode_isCaseMarker (lastStmt)
6476                   && !exprNode_isDefaultMarker (lastStmt)
6477                   && !exprNode_isLabelMarker (lastStmt))
6478                 {
6479                   voptgenerror (FLG_CASEBREAK,
6480                                 cstring_makeLiteral 
6481                                 ("Fall through case (no preceding break)"),
6482                                 e2->loc);
6483                 }
6484             }
6485         }
6486     }
6487
6488   exprNode_mergeUSs (ret, e2);
6489   
6490   usymtab_setExitCode (ret->exitCode);
6491   
6492   if (ret->mustBreak)
6493     {
6494       usymtab_setMustBreak ();
6495     }
6496
6497   return ret;
6498 }
6499
6500 exprNode exprNode_createTok (/*@only@*/ lltok t)
6501 {
6502   exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6503   ret = exprNode_create (ctype_unknown);
6504   ret->kind = XPR_TOK;
6505   ret->edata = exprData_makeTok (t);
6506   return ret;
6507 }
6508
6509 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6510 {
6511   if (!exprNode_isError (e))
6512     {
6513       exprNode_checkStatement(e);
6514     }
6515
6516   return (exprNode_statementError (e, t));
6517 }
6518
6519 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6520 {
6521   exprNode ret = exprNode_createPartialCopy (e);
6522
6523   if (!exprNode_isError (e))
6524     {
6525       if (e->kind != XPR_ASSIGN)
6526         {
6527           exprNode_checkUse (ret, e->sref, e->loc);
6528         }
6529
6530       ret->exitCode = e->exitCode;
6531       ret->canBreak = e->canBreak;
6532       ret->mustBreak = e->mustBreak;
6533     }
6534   
6535   ret->edata = exprData_makeUop (e, t);
6536   ret->kind = XPR_STMT;
6537
6538   return ret;
6539 }
6540
6541 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6542 {
6543   if (!exprNode_isError (e))
6544     {
6545       if (e->kind != XPR_ASSIGN)
6546         {
6547           exprNode_checkUse (e, e->sref, e->loc);
6548         }
6549     }
6550
6551   return e;
6552 }
6553
6554 void exprNode_produceGuards (exprNode pred)
6555 {
6556   if (!exprNode_isError (pred))
6557     {
6558       if (ctype_isRealPointer (pred->typ))
6559         {
6560           pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6561         }
6562       
6563       exprNode_checkUse (pred, pred->sref, pred->loc);
6564       exprNode_resetSref (pred);
6565     }
6566 }
6567
6568 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6569 {
6570   exprNode ret = exprNode_createPartialCopy (e);
6571
6572   if (!exprNode_isError (e))
6573     {
6574       ret->exitCode = e->exitCode;
6575       ret->canBreak = e->canBreak;
6576       ret->mustBreak = e->mustBreak;
6577     }
6578   
6579   ret->edata = exprData_makeSingle (e);
6580   ret->kind = XPR_BLOCK;
6581   return ret;
6582 }
6583
6584 bool exprNode_isBlock (exprNode e)
6585 {
6586   return (exprNode_isDefined (e) 
6587           && ((e)->kind == XPR_BLOCK));
6588 }
6589  
6590 bool exprNode_isAssign (exprNode e)
6591 {
6592   if (exprNode_isDefined (e))
6593     {
6594       return (e->kind == XPR_ASSIGN);
6595     }
6596
6597   return FALSE;
6598 }
6599
6600 bool exprNode_isEmptyStatement (exprNode e)
6601 {
6602   return (exprNode_isDefined (e) 
6603           && (e->kind == XPR_TOK)
6604           && (lltok_isSemi (exprData_getTok (e->edata))));
6605 }
6606
6607 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6608 {
6609   exprNode ret;
6610   bool emptyErr = FALSE;
6611
6612   if (context_maybeSet (FLG_IFEMPTY))
6613     {
6614       if (exprNode_isEmptyStatement (tclause))
6615         {
6616           emptyErr = optgenerror (FLG_IFEMPTY,
6617                                   cstring_makeLiteral
6618                                   ("Body of if statement is empty"),
6619                                   exprNode_loc (tclause));
6620         }
6621     }
6622
6623   if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6624     {
6625       if (exprNode_isDefined (tclause)
6626           && !exprNode_isBlock (tclause))
6627         {
6628           voptgenerror (FLG_IFBLOCK,
6629                         message
6630                         ("Body of if statement is not a block: %s",
6631                          exprNode_unparse (tclause)),
6632                         exprNode_loc (tclause));
6633         }
6634     }
6635
6636   if (exprNode_isError (pred))
6637     {
6638       if (exprNode_isError (tclause))
6639         {
6640           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6641         }
6642       else
6643         {
6644           ret = exprNode_createPartialCopy (tclause);
6645         }
6646     }
6647   else
6648     {
6649       if (exprNode_mustEscape (pred))
6650         {
6651           voptgenerror 
6652             (FLG_UNREACHABLE,
6653              message ("Predicate always exits: %s", exprNode_unparse (pred)),
6654              exprNode_loc (pred));
6655         }
6656
6657       exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6658       exprNode_checkUse (pred, pred->sref, pred->loc);
6659       
6660       if (!exprNode_isError (tclause))
6661         {
6662           exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6663         }
6664       
6665       ret = exprNode_createPartialCopy (pred);
6666     }
6667
6668   ret->kind = XPR_IF;
6669   ret->edata = exprData_makePair (pred, tclause);
6670
6671   ret->exitCode = XK_UNKNOWN;
6672
6673   if (exprNode_isDefined (tclause))
6674     {
6675       ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6676       ret->canBreak = tclause->canBreak;
6677       ret->sets = sRefSet_union (ret->sets, tclause->sets);
6678       ret->msets = sRefSet_union (ret->msets, tclause->msets);
6679       ret->uses = sRefSet_union (ret->uses, tclause->uses);
6680     }
6681
6682   ret->mustBreak = FALSE;
6683
6684   return ret;
6685 }
6686
6687 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6688                           /*@only@*/ exprNode tclause, 
6689                           /*@only@*/ exprNode eclause)
6690 {
6691   exprNode ret;
6692   bool tEmptyErr = FALSE;
6693   bool eEmptyErr = FALSE;
6694
6695   if (context_maybeSet (FLG_IFEMPTY))
6696     {
6697       if (exprNode_isEmptyStatement (tclause))
6698         {
6699           tEmptyErr = optgenerror 
6700             (FLG_IFEMPTY,
6701              cstring_makeLiteral
6702              ("Body of if clause of if statement is empty"),
6703              exprNode_loc (tclause));
6704         }
6705
6706       if (exprNode_isEmptyStatement (eclause))
6707         {
6708           eEmptyErr = optgenerror 
6709             (FLG_IFEMPTY,
6710              cstring_makeLiteral
6711              ("Body of else clause of if statement is empty"),
6712              exprNode_loc (eclause));
6713         }
6714     }
6715
6716   if (context_maybeSet (FLG_IFBLOCK))
6717     {
6718       if (!tEmptyErr
6719           && exprNode_isDefined (tclause)
6720           && !exprNode_isBlock (tclause))
6721         {
6722           voptgenerror (FLG_IFBLOCK,
6723                         message
6724                         ("Body of if clause of if statement is not a block: %s",
6725                          exprNode_unparse (tclause)),
6726                         exprNode_loc (tclause));
6727         }
6728
6729       if (!eEmptyErr
6730           && exprNode_isDefined (eclause)
6731           && !exprNode_isBlock (eclause)
6732           && !(eclause->kind == XPR_IF)
6733           && !(eclause->kind == XPR_IFELSE))
6734         {
6735           voptgenerror
6736             (FLG_IFBLOCK,
6737              message
6738              ("Body of else clause of if statement is not a block: %s",
6739               exprNode_unparse (eclause)),
6740              exprNode_loc (eclause));
6741         }
6742     }
6743
6744   if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6745     {
6746       if (exprNode_isDefined (eclause)
6747           && (eclause->kind == XPR_IF))
6748         {
6749           voptgenerror (FLG_ELSEIFCOMPLETE,
6750                         message ("Incomplete else if logic (no final else): %s",
6751                                  exprNode_unparse (eclause)),
6752                         exprNode_loc (eclause));
6753         }
6754     }
6755
6756   if (exprNode_isError (pred))
6757     {
6758       if (exprNode_isError (tclause))
6759         {
6760           if (exprNode_isError (eclause))
6761             {
6762               ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6763             }
6764           else
6765             {
6766               ret = exprNode_createPartialCopy (eclause);
6767             }
6768         }
6769       else 
6770         {
6771           ret = exprNode_createPartialCopy (tclause);
6772         }
6773     }
6774   else /* pred is okay */
6775     {
6776       ret = exprNode_createPartialCopy (pred);
6777
6778       if (exprNode_mustEscape (pred))
6779         {
6780           voptgenerror
6781             (FLG_UNREACHABLE,
6782              message ("Predicate always exits: %s", exprNode_unparse (pred)),
6783              exprNode_loc (pred));
6784         }
6785       
6786       exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6787       exprNode_checkUse (ret, pred->sref, pred->loc);
6788       
6789       exprNode_mergeCondUSs (ret, tclause, eclause);
6790     }
6791
6792   ret->kind = XPR_IFELSE;
6793   ret->edata = exprData_makeCond (pred, tclause, eclause);
6794
6795   if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6796     {
6797       exprNode_combineControl (ret, tclause, eclause);
6798       ret->loc = fileloc_update (ret->loc, eclause->loc);
6799     }
6800
6801   return ret;
6802 }
6803
6804 /*
6805 ** *allpaths <- TRUE iff all executions paths must go through the switch
6806 */
6807
6808 static bool
6809 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6810 {
6811   exprNodeSList el = exprNode_flatten (e);
6812   bool mustReturn = TRUE; /* find a branch that doesn't */
6813   bool thisReturn = FALSE;
6814   bool hasDefault = FALSE;
6815   bool hasAllMembers = FALSE;
6816   bool inSwitch = FALSE;
6817   bool isEnumSwitch = FALSE;
6818   bool canBreak = FALSE;
6819   bool fallThrough = FALSE;
6820   ctype ct = ctype_unknown;
6821   enumNameSList usedEnums;
6822   enumNameList enums;
6823
6824   if (exprNode_isDefined (test))
6825     {
6826       ctype ttype;
6827
6828       ct = test->typ;
6829       ttype = ctype_realType (ct);
6830
6831       if (ctype_isEnum (ttype))
6832         {
6833           isEnumSwitch = TRUE;
6834           enums = ctype_elist (ttype);
6835           usedEnums = enumNameSList_new ();
6836         }
6837     }
6838
6839   exprNodeSList_elements (el, current)
6840     {
6841       if (exprNode_isDefined (current))
6842         {
6843           switch (current->kind)
6844             {
6845             case XPR_FTDEFAULT:
6846             case XPR_DEFAULT:
6847               if (hasDefault)
6848                 {
6849                   voptgenerror 
6850                     (FLG_CONTROL,
6851                      message ("Duplicate default cases in switch"),
6852                      exprNode_loc (current));
6853                 }          
6854             /*@fallthrough@*/
6855             case XPR_FTCASE:
6856             case XPR_CASE: 
6857               if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6858                 {
6859                   hasDefault = TRUE; 
6860                 }
6861               else
6862                 {
6863                   if (isEnumSwitch)
6864                     {
6865                       exprNode st = exprData_getSingle (current->edata);
6866                       uentry ue = exprNode_getUentry (st);
6867                       
6868                       if (uentry_isValid (ue))
6869                         {
6870                           cstring cname = uentry_rawName (ue);
6871                           
6872                           if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6873                             {
6874                               if (enumNameSList_member
6875                                   (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6876                                 {
6877                                   voptgenerror
6878                                     (FLG_CONTROL,
6879                                      message ("Duplicate case in switch: %s", 
6880                                               cname),
6881                                      current->loc);
6882                                 }
6883                               else
6884                                 {
6885                                   enumNameSList_addh (usedEnums, cname);
6886                                 }
6887                             }
6888                           else
6889                             {
6890                               voptgenerror 
6891                                 (FLG_TYPE,
6892                                  message ("Case in switch not %s member: %s", 
6893                                           ctype_unparse (ct), cname),
6894                                  current->loc);
6895                             }
6896                         }
6897                     }
6898                 }
6899               
6900               if (inSwitch && !fallThrough)
6901                 {
6902                   if (!thisReturn || canBreak) 
6903                     {
6904                       mustReturn = FALSE;
6905                     }
6906                 }
6907               
6908               fallThrough = TRUE;
6909               inSwitch = TRUE;
6910               thisReturn = FALSE;
6911               canBreak = FALSE;
6912               /*@switchbreak@*/ break;
6913             default:
6914               thisReturn = thisReturn || exprNode_mustEscape (current);
6915               canBreak = canBreak || current->canBreak;
6916               if (canBreak) fallThrough = FALSE;
6917             }
6918         }
6919     } end_exprNodeSList_elements;
6920
6921   if (inSwitch) /* check the last one! */
6922     {
6923       if (!thisReturn || canBreak) 
6924         {
6925           mustReturn = FALSE;
6926         }
6927     }
6928   
6929   if (isEnumSwitch)
6930     {
6931       if (!hasDefault 
6932           && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) != 
6933               enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6934         {
6935           enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6936           
6937           voptgenerror (FLG_MISSCASE,
6938                         message ("Missing case%s in switch: %q",
6939                                  cstring_makeLiteralTemp 
6940                                  ((enumNameSList_size (unused) > 1) ? "s" : ""),
6941                                  enumNameSList_unparse (unused)),
6942                         g_currentloc);
6943
6944           enumNameSList_free (unused);
6945         }
6946       else
6947         {
6948           hasAllMembers = TRUE;
6949           *allpaths = TRUE;
6950         }
6951
6952       enumNameSList_free (usedEnums);
6953     }
6954   else
6955     {
6956       *allpaths = hasDefault;
6957     }
6958
6959   exprNodeSList_free (el);
6960   return ((hasDefault || hasAllMembers) && mustReturn);  
6961 }
6962     
6963 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6964 {
6965   exprNode ret = exprNode_createPartialCopy (e);
6966   bool allpaths;
6967
6968   DPRINTF (("Switch: %s", exprNode_unparse (s)));
6969
6970   ret->kind = XPR_SWITCH;
6971   ret->edata = exprData_makePair (e, s);
6972   
6973   if (!exprNode_isError (s))
6974     {
6975       exprNode fs = exprNode_firstStatement (s);
6976       ret->loc = fileloc_update (ret->loc, s->loc);
6977
6978       if (exprNode_isUndefined (fs) 
6979           || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6980           || exprNode_isDefaultMarker (fs)) {
6981         ;
6982       } else {
6983         voptgenerror (FLG_FIRSTCASE,
6984                       message
6985                       ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6986                       fs->loc);
6987       }
6988     }
6989
6990   if (!exprNode_isError (e)) 
6991     {
6992       if (checkSwitchExpr (e, s, &allpaths))
6993         {
6994           ret->exitCode = XK_MUSTRETURN;
6995         }
6996       else
6997         {
6998           ret->exitCode = e->exitCode;
6999         }
7000
7001       ret->canBreak = e->canBreak;
7002       ret->mustBreak = e->mustBreak;
7003     }
7004   /*
7005   ** forgot this!
7006   **   exprNode.c:3883,32: Variable allpaths used before definition
7007   */
7008   else 
7009     {
7010       allpaths = FALSE;
7011     }
7012   
7013   DPRINTF (("Context exit switch!"));
7014   context_exitSwitch (ret, allpaths);
7015   DPRINTF (("Context exit switch done!"));
7016
7017   return ret;
7018 }
7019
7020 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7021                                /*@notnull@*/ exprNode body)
7022 {
7023   sRefSet tuses = test->uses;
7024   
7025   if (!sRefSet_isEmpty (test->uses))
7026     {
7027       sRefSet sets = sRefSet_newCopy (body->sets);
7028       bool hasError = TRUE;
7029       bool innerState = FALSE;
7030       sRefSet tuncon = sRefSet_undefined;
7031       
7032       sets = sRefSet_union (sets, test->sets);
7033       sets = sRefSet_union (sets, body->msets);
7034       sets = sRefSet_union (sets, test->msets);
7035
7036       sRefSet_allElements (tuses, el)
7037         {
7038           if (sRef_isUnconstrained (el))
7039             {
7040               tuncon = sRefSet_insert (tuncon, el);
7041             }
7042           else
7043             {
7044               if (sRefSet_member (sets, el))
7045                 {
7046                   hasError = FALSE;
7047                   break;
7048                 }
7049             }
7050
7051           if (sRef_isInternalState (el)
7052               || sRef_isFileStatic (sRef_getRootBase (el)))
7053             {
7054               innerState = TRUE;
7055             }
7056         } end_sRefSet_allElements ;
7057
7058       if (hasError)
7059         {
7060           sRefSet suncon = sRefSet_undefined;
7061           bool sinner = FALSE;
7062
7063           sRefSet_allElements (sets, el)
7064             {
7065               if (sRef_isUnconstrained (el))
7066                 {
7067                   suncon = sRefSet_insert (suncon, el);
7068                 }
7069               else if (sRef_isInternalState (el))
7070                 {
7071                   sinner = TRUE;
7072                 }
7073               else
7074                 {
7075                   ;
7076                 }
7077             } end_sRefSet_allElements ;
7078
7079           if (sinner && innerState)
7080             {
7081               ; 
7082             }
7083           else if (sRefSet_isEmpty (tuncon)
7084                    && sRefSet_isEmpty (suncon))
7085             {
7086               voptgenerror 
7087                 (FLG_INFLOOPS,
7088                  message
7089                  ("Suspected infinite loop.  No value used in loop test (%q) "
7090                   "is modified by test or loop body.",
7091                   sRefSet_unparsePlain (tuses)), 
7092                  test->loc);
7093             }
7094           else
7095             {
7096               if (sRefSet_isEmpty (tuncon))
7097                 {
7098                   voptgenerror 
7099                     (FLG_INFLOOPSUNCON,
7100                      message ("Suspected infinite loop.  No condition values "
7101                               "modified.  Modification possible through "
7102                               "unconstrained calls: %q",
7103                               sRefSet_unparsePlain (suncon)), 
7104                      test->loc);
7105                 }
7106               else
7107                 {
7108                   voptgenerror 
7109                     (FLG_INFLOOPSUNCON,
7110                      message ("Suspected infinite loop.  No condition values "
7111                               "modified.  Possible undetected dependency through "
7112                               "unconstrained calls in loop test: %q",
7113                               sRefSet_unparsePlain (tuncon)), 
7114                      test->loc);
7115                 }
7116             }
7117         }
7118
7119       sRefSet_free (sets);
7120     }
7121 }
7122
7123 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7124 {
7125   exprNode ret;
7126   bool emptyErr = FALSE;
7127   
7128   if (context_maybeSet (FLG_WHILEEMPTY))
7129     {
7130       if (exprNode_isEmptyStatement (b))
7131         {
7132           emptyErr = optgenerror 
7133             (FLG_WHILEEMPTY,
7134              cstring_makeLiteral
7135              ("Body of while statement is empty"),
7136              exprNode_loc (b));
7137         }
7138     }
7139
7140   if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7141     {
7142       if (exprNode_isDefined (b)
7143           && !exprNode_isBlock (b))
7144         {
7145           if (context_inIterDef ()
7146               && (b->kind == XPR_STMTLIST
7147                   || b->kind == XPR_TOK))
7148             {
7149               ; /* no error */
7150             }
7151           else
7152             {
7153               voptgenerror (FLG_WHILEBLOCK,
7154                             message
7155                             ("Body of while statement is not a block: %s",
7156                              exprNode_unparse (b)),
7157                             exprNode_loc (b));
7158             }
7159         }
7160     }
7161   
7162   if (exprNode_isError (t))
7163     {
7164       if (exprNode_isError (b))
7165         {
7166           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7167         }
7168       else
7169         {
7170           ret = exprNode_createPartialCopy (b);
7171         }
7172     }
7173   else
7174     {
7175       exprNode test;
7176
7177       ret = exprNode_createPartialCopy (t);
7178       
7179       llassert (t->kind == XPR_WHILEPRED);
7180
7181       test = exprData_getSingle (t->edata);
7182
7183       if (!exprNode_isError (b) && exprNode_isDefined (test))
7184         {
7185           if (context_maybeSet (FLG_INFLOOPS)
7186               || context_maybeSet (FLG_INFLOOPSUNCON))
7187             {
7188               /*
7189               ** check that some variable in the predicate is set by the body
7190               ** if the predicate uses any variables
7191               */
7192               
7193               checkInfiniteLoop (test, b);
7194             }
7195
7196           exprNode_mergeUSs (ret, b);
7197
7198           if (exprNode_isDefined (b))
7199             {
7200               ret->exitCode = exitkind_makeConditional (b->exitCode);
7201             }
7202         }
7203     }
7204   
7205   ret->edata = exprData_makePair (t, b);
7206   ret->kind = XPR_WHILE;
7207
7208   if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7209     {
7210       voptgenerror
7211         (FLG_CONTROL,
7212          message ("Predicate always exits: %s", exprNode_unparse (t)),
7213          exprNode_loc (t));
7214     }
7215
7216   ret->exitCode = XK_NEVERESCAPE;
7217
7218   /*
7219   ** If loop is infinite, and there is no break inside, 
7220   ** exit code is never reach. 
7221   */
7222
7223   if (exprNode_knownIntValue (t))
7224     {
7225       if (!exprNode_isZero (t)) 
7226         {
7227           if (exprNode_isDefined (b)) 
7228             {
7229               if (!b->canBreak) 
7230                 {
7231                   /* Really, it means never reached. */
7232                   ret->exitCode = XK_MUSTEXIT;
7233                 }
7234             }
7235         }
7236     } 
7237   else 
7238     {
7239       ;
7240     }
7241
7242   ret->canBreak = FALSE;
7243   ret->mustBreak = FALSE;
7244
7245   return ret; 
7246 }
7247
7248 /*
7249 ** do { b } while (t);
7250 ** 
7251 ** note: body passed as first argument 
7252 */
7253
7254 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7255 {
7256   exprNode ret;
7257   
7258   if (exprNode_isError (t))
7259     {
7260       if (exprNode_isError (b))
7261         {
7262           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7263         }
7264       else
7265         {
7266           ret = exprNode_createPartialCopy (b);
7267
7268           ret->exitCode = exitkind_makeConditional (b->exitCode);
7269           exprNode_checkUse (ret, b->sref, b->loc);
7270           ret->exitCode = b->exitCode;
7271           ret->canBreak = b->canBreak;
7272           ret->mustBreak = b->mustBreak;
7273         }
7274     }
7275   else
7276     {
7277       ret = exprNode_createPartialCopy (t);
7278       exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7279       
7280       if (!exprNode_isError (b)) 
7281         {
7282           /*
7283           ** forgot the copy's --- why wasn't this detected??
7284           */
7285
7286           ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7287           ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7288           ret->uses = sRefSet_copyInto (ret->uses, b->uses);  
7289
7290           /* left this out --- causes and aliasing bug (infinite loop)
7291              should be detected?? */
7292
7293           exprNode_checkUse (ret, b->sref, b->loc);
7294           exprNode_mergeUSs (ret, t);
7295           exprNode_checkUse (ret, t->sref, t->loc);
7296
7297           ret->exitCode = b->exitCode;
7298           ret->canBreak = b->canBreak;
7299           ret->mustBreak = b->mustBreak;
7300         }
7301     }
7302   
7303   context_exitDoWhileClause (t);
7304
7305   ret->kind = XPR_DOWHILE;
7306   ret->edata = exprData_makePair (t, b);
7307   return ret;
7308 }
7309
7310 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7311 {
7312   exprNode ret;
7313   bool emptyErr = FALSE;
7314
7315   if (context_maybeSet (FLG_FOREMPTY))
7316     {
7317       if (exprNode_isEmptyStatement (body))
7318         {
7319           emptyErr = optgenerror 
7320             (FLG_FOREMPTY,
7321              cstring_makeLiteral
7322              ("Body of for statement is empty"),
7323              exprNode_loc (body));
7324         }
7325     }
7326
7327   if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7328     {
7329       if (exprNode_isDefined (body)
7330           && !exprNode_isBlock (body))
7331         {
7332           if (context_inIterDef ()
7333               && (body->kind == XPR_STMTLIST
7334                   || body->kind == XPR_TOK))
7335             {
7336               ; /* no error */
7337             }
7338           else
7339             {
7340               voptgenerror (FLG_FORBLOCK,
7341                             message
7342                             ("Body of for statement is not a block: %s",
7343                              exprNode_unparse (body)),
7344                             exprNode_loc (body));
7345             }
7346         }
7347     }
7348
7349   /*
7350   ** for ud purposes:  (alreadly) init -> test -> (now) LOOP: body + inc + test
7351   */
7352
7353   if (exprNode_isError (body))
7354     {
7355       ret = exprNode_createPartialCopy (inc);
7356     }
7357   else
7358     {
7359       ret = exprNode_createPartialCopy (body);
7360       
7361       ret->exitCode = exitkind_makeConditional (body->exitCode);
7362
7363             exprNode_mergeUSs (inc, body);
7364       
7365       if (exprNode_isDefined (inc))
7366         {
7367           exprNode tmp;
7368
7369           context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7370      
7371           
7372           tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7373           exprNode_freeShallow (tmp); 
7374
7375           context_clearMessageAnnote ();
7376           context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7377
7378           tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7379           exprNode_freeShallow (tmp);
7380
7381           context_clearMessageAnnote ();
7382
7383           ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7384           ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7385           ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7386         }
7387     }
7388
7389   ret->kind = XPR_FOR;
7390   ret->edata = exprData_makePair (inc, body);
7391
7392   if (exprNode_isDefined (inc)) {
7393     exprNode test = exprData_getTripleTest (inc->edata);
7394
7395     if (exprNode_isUndefined (test)) {
7396       if (exprNode_isDefined (body)) {
7397         if (!body->canBreak) {
7398           /* Really, it means never reached. */
7399           ret->exitCode = XK_MUSTEXIT;
7400         }
7401       }
7402     }
7403   }
7404
7405   return (ret);
7406 }
7407
7408 /*
7409 ** for (init; test; inc)
7410 ** ==>
7411 ** init;
7412 ** while (test) { body; inc; } 
7413 **
7414 ** Now: check use of init (may set vars for test)
7415 **      check use of test
7416 **      no checks on inc
7417 _*/
7418
7419 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7420 {
7421   exprNode test;
7422
7423   if (exprNode_isError (pred)) return guardSet_undefined;
7424
7425   llassert (pred->kind == XPR_FORPRED);
7426
7427   test = exprData_getTripleTest (pred->edata);
7428
7429   if (!exprNode_isError (test))
7430     {
7431       return (test->guards);
7432     }
7433
7434   return guardSet_undefined;
7435 }
7436
7437 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7438 {
7439   exprNode ret = exprNode_createSemiCopy (test);
7440
7441   if (exprNode_isDefined (test))
7442     {
7443       exprNode_copySets (ret, test);
7444       exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7445       exprNode_checkUse (ret, test->sref, test->loc);
7446       
7447       exprNode_produceGuards (test);
7448       
7449       ret->guards = guardSet_copy (test->guards);
7450     }
7451
7452   ret->edata = exprData_makeSingle (test);
7453   ret->kind = XPR_WHILEPRED;
7454   return ret;
7455 }
7456
7457 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test, 
7458                            /*@only@*/ exprNode inc)
7459 {
7460   exprNode ret;
7461   
7462   /*
7463   ** for ud purposes:  init -> test -> LOOP: [ body, inc ]
7464   */
7465   
7466   exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7467
7468   if (!exprNode_isError (inc)) 
7469     {
7470       ret = exprNode_createPartialCopy (inc);
7471     }
7472   else 
7473     {
7474       if (!exprNode_isError (init)) 
7475         {
7476           ret = exprNode_createPartialCopy (init);
7477         }
7478       else if (!exprNode_isError (test)) 
7479         {
7480           ret = exprNode_createPartialCopy (test);
7481         }
7482       else 
7483         {
7484           ret = exprNode_createUnknown ();
7485         }
7486     }
7487
7488   exprNode_mergeUSs (ret, init);
7489
7490   if (exprNode_isDefined (init))
7491     {
7492       exprNode_checkUse (ret, init->sref, init->loc);
7493     }
7494
7495   exprNode_mergeUSs (ret, test);
7496
7497   if (exprNode_isDefined (test))
7498     {
7499       exprNode_checkUse (ret, test->sref, test->loc);
7500     }
7501
7502   ret->kind = XPR_FORPRED;
7503   ret->edata = exprData_makeFor (init, test, inc); 
7504   return (ret);
7505 }
7506
7507 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7508 {
7509   exprNode ret = exprNode_createUnknown ();
7510
7511   if (context_inMacro ())
7512     {
7513       voptgenerror (FLG_MACROSTMT,
7514                     message ("Macro %s uses goto (not functional)", 
7515                              context_inFunctionName ()),
7516                     g_currentloc);
7517     }
7518   
7519   ret->kind = XPR_GOTO;
7520   ret->edata = exprData_makeLiteral (label);
7521   ret->mustBreak = TRUE;
7522   ret->exitCode = XK_GOTO;
7523   ret->canBreak = TRUE;
7524   return ret;
7525 }
7526
7527 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7528 {
7529   exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7530
7531   ret->kind = XPR_CONTINUE;
7532   ret->edata = exprData_makeTok (l);
7533   ret->canBreak = TRUE;
7534   ret->mustBreak = TRUE;
7535
7536   if (qcontinue == QSAFEBREAK)
7537     {
7538       ; /* no checking */
7539     }
7540   else if (qcontinue == QINNERCONTINUE)
7541     {
7542       if (!context_inDeepLoop ())
7543         {
7544           voptgenerror 
7545             (FLG_LOOPLOOPCONTINUE,
7546              cstring_makeLiteral ("Continue statement marked with innercontinue "
7547                                   "is not inside a nested loop"),
7548              exprNode_loc (ret));
7549         }
7550     }
7551   else if (qcontinue == BADTOK)
7552     {
7553       if (context_inDeepLoop ())
7554         {
7555           voptgenerror 
7556             (FLG_LOOPLOOPCONTINUE,
7557              cstring_makeLiteral ("Continue statement in nested loop"),
7558              exprNode_loc (ret));
7559         }
7560     }
7561   else
7562     {
7563       llbuglit ("exprNode_continue: bad qcontinue");
7564     }
7565
7566   return ret;
7567 }
7568
7569 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7570 {
7571   exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7572   clause breakClause = context_breakClause ();
7573   
7574   ret->kind = XPR_BREAK;
7575   ret->edata = exprData_makeTok (l);
7576   ret->canBreak = TRUE;
7577   ret->mustBreak = TRUE;
7578   
7579   if (breakClause == NOCLAUSE)
7580     {
7581       voptgenerror 
7582         (FLG_SYNTAX,
7583          cstring_makeLiteral ("Break not inside while, for or switch statement"),
7584          exprNode_loc (ret));
7585     }
7586   else
7587     {
7588       if (bqual != BADTOK)
7589         {
7590           switch (bqual)
7591             {
7592             case QSAFEBREAK:
7593               break;
7594             case QINNERBREAK:
7595               if (breakClause == SWITCHCLAUSE)
7596                 {
7597                   if (!context_inDeepSwitch ())
7598                     {
7599                       voptgenerror (FLG_SYNTAX,
7600                                     cstring_makeLiteral 
7601                                     ("Break preceded by innerbreak is not in a deep switch"),
7602                                     exprNode_loc (ret));
7603                     }
7604                 }
7605               else 
7606                 {
7607                   if (!context_inDeepLoop ())
7608                     {
7609                       voptgenerror (FLG_SYNTAX,
7610                                     cstring_makeLiteral 
7611                                     ("Break preceded by innerbreak is not in a deep loop"),
7612                                     exprNode_loc (ret));
7613                     }
7614                 }
7615               break;
7616             case QLOOPBREAK:
7617               if (breakClause == SWITCHCLAUSE)
7618                 {
7619                   voptgenerror (FLG_SYNTAX,
7620                                 cstring_makeLiteral 
7621                                 ("Break preceded by loopbreak is breaking a switch"),
7622                                 exprNode_loc (ret));
7623                 }
7624               break;
7625             case QSWITCHBREAK:
7626               if (breakClause != SWITCHCLAUSE)
7627                 {
7628                   voptgenerror 
7629                     (FLG_SYNTAX,
7630                      message ("Break preceded by switchbreak is breaking %s",
7631                               cstring_makeLiteralTemp 
7632                               ((breakClause == WHILECLAUSE
7633                                 || breakClause == DOWHILECLAUSE) ? "a while loop"
7634                                : (breakClause == FORCLAUSE) ? "a for loop"
7635                                : (breakClause == ITERCLAUSE) ? "an iterator"
7636                                : "<error loop>")),
7637                      exprNode_loc (ret));
7638                 }
7639               break;
7640             BADDEFAULT;
7641             }
7642         }
7643       else
7644         {
7645           if (breakClause == SWITCHCLAUSE)
7646             {
7647               clause nextBreakClause = context_nextBreakClause ();
7648
7649               switch (nextBreakClause)
7650                 {
7651                 case NOCLAUSE: break;
7652                 case WHILECLAUSE:
7653                 case DOWHILECLAUSE:
7654                 case FORCLAUSE:
7655                 case ITERCLAUSE:
7656                   voptgenerror 
7657                     (FLG_LOOPSWITCHBREAK,
7658                      cstring_makeLiteral ("Break statement in switch inside loop"),
7659                      exprNode_loc (ret));
7660                   break;
7661                 case SWITCHCLAUSE:
7662                   voptgenerror 
7663                     (FLG_SWITCHSWITCHBREAK,
7664                      cstring_makeLiteral ("Break statement in switch inside switch"),
7665                      exprNode_loc (ret));
7666                   break;
7667                 BADDEFAULT;
7668                 }
7669             }
7670           else
7671             {
7672               if (context_inDeepLoop ())
7673                 {
7674                   voptgenerror 
7675                     (FLG_LOOPLOOPBREAK,
7676                      cstring_makeLiteral ("Break statement in nested loop"),
7677                      exprNode_loc (ret));
7678                 }
7679               else 
7680                 {
7681                   if (context_inDeepLoopSwitch ())
7682                     {
7683                       voptgenerror 
7684                         (FLG_SWITCHLOOPBREAK,
7685                          cstring_makeLiteral ("Break statement in loop inside switch"),
7686                          exprNode_loc (ret));
7687                     }
7688                 }
7689             }
7690         }
7691     }
7692
7693   return ret;
7694 }
7695
7696 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7697 {
7698   fileloc loc = lltok_getLoc (t);
7699   exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7700   
7701   context_returnFunction ();
7702   exprChecks_checkNullReturn (loc);
7703
7704   ret->kind = XPR_NULLRETURN;
7705   ret->edata = exprData_makeTok (t);
7706   ret->exitCode = XK_MUSTRETURN;
7707   return ret;
7708 }
7709
7710 exprNode exprNode_return (/*@only@*/ exprNode e)
7711 {
7712   exprNode ret;
7713   
7714   if (exprNode_isError (e))
7715     {
7716       ret = exprNode_createUnknown ();
7717     }
7718   else
7719     {
7720       ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7721
7722       exprNode_checkUse (ret, e->sref, e->loc);
7723       exprNode_checkReturn (e);
7724     }
7725
7726   context_returnFunction ();
7727   ret->kind = XPR_RETURN;
7728   ret->edata = exprData_makeSingle (e);
7729   ret->exitCode = XK_MUSTRETURN;
7730
7731   return (ret);
7732 }
7733
7734 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7735 {
7736   exprNode ret;
7737
7738   if (exprNode_isError (e1)) 
7739     {
7740       if (exprNode_isError (e2))
7741         {
7742           ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7743         }
7744       else
7745         {
7746           ret = exprNode_createPartialCopy (e2);
7747           exprNode_checkUse (ret, e2->sref, e2->loc);
7748           ret->sref = e2->sref;
7749         }
7750     }
7751   else
7752     {
7753       ret = exprNode_createPartialCopy (e1);
7754
7755       exprNode_checkUse (ret, e1->sref, e1->loc);
7756
7757       if (!exprNode_isError (e2))
7758         {
7759           exprNode_mergeUSs (ret, e2);
7760           exprNode_checkUse (ret, e2->sref, e2->loc);
7761           ret->sref = e2->sref;
7762         }
7763     }
7764
7765   ret->kind = XPR_COMMA;
7766   ret->edata = exprData_makePair (e1, e2);
7767   
7768   if (exprNode_isDefined (e1))
7769     {
7770       if (exprNode_isDefined (e2))
7771         {
7772           ret->typ = e2->typ; 
7773
7774           if (exprNode_mustEscape (e1) || e1->mustBreak)
7775             {
7776               voptgenerror 
7777                 (FLG_UNREACHABLE,
7778                  message ("Second clause of comma expression is unreachable: %s",
7779                           exprNode_unparse (e2)), 
7780                  exprNode_loc (e2));
7781             }
7782           
7783           ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7784           ret->mustBreak = e1->mustBreak || e2->mustBreak;
7785           ret->canBreak = e1->canBreak || e2->canBreak;
7786         }
7787       else
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 = e1->exitCode;
7799           ret->canBreak = e1->canBreak;
7800         }
7801     }
7802   else
7803     {
7804       if (exprNode_isDefined (e2))
7805         {
7806           ret->exitCode = e2->exitCode;
7807           ret->mustBreak = e2->mustBreak;
7808           ret->canBreak = e2->canBreak;
7809         }
7810     }
7811
7812   return (ret);
7813 }
7814
7815 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7816 {
7817   ctype t1 = exprNode_getType (el);
7818   ctype t2 = exprNode_getType (val);
7819   bool hasError = FALSE;
7820   
7821   if (ctype_isUnknown (t1))
7822     {
7823       voptgenerror (FLG_IMPTYPE,
7824                     message ("Variable has unknown (implicitly int) type: %s",
7825                              exprNode_unparse (el)),
7826                     el->loc);
7827       
7828       t1 = ctype_int;
7829       el->typ = ctype_int;
7830     }
7831
7832   if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7833     {
7834       exprNodeList vals = exprData_getArgs (val->edata);
7835
7836       if (ctype_isRealAP (t1))
7837         {
7838           int i = 0;
7839           int nerrors = 0;
7840
7841           /*@i423 check number of entries int a[3] = { 1, 2, 3, 4 } ; */
7842
7843           exprNodeList_elements (vals, oneval)
7844             {
7845               cstring istring = message ("%d", i);
7846               exprNode newel =
7847                 exprNode_arrayFetch 
7848                   (exprNode_fakeCopy (el),
7849                    exprNode_numLiteral (ctype_int, istring,
7850                                         fileloc_copy (el->loc), i));
7851               
7852               if (exprNode_isDefined (newel))
7853                 {
7854                   if (exprNodeList_size (vals) == 1
7855                       && ctype_isString (exprNode_getType (oneval))
7856                       && ctype_isChar (exprNode_getType (newel)))
7857                     {
7858                       exprNode_freeIniter (newel);
7859                     }
7860                   else
7861                     {
7862                       if (exprNode_checkOneInit (newel, oneval))
7863                         {
7864                           hasError = TRUE;
7865                           nerrors++;
7866                           
7867                           if (nerrors > 3 && exprNodeList_size (vals) > 6)
7868                             {
7869                               llgenmsg 
7870                                 (message ("Additional initialization errors "
7871                                           "for %s not reported",
7872                                           exprNode_unparse (el)),
7873                                  exprNode_loc (el));
7874                               exprNode_freeIniter (newel);
7875                               break;
7876                             }
7877                           else
7878                             {
7879                               exprNode_freeIniter (newel);
7880                             }
7881                         }
7882                       else
7883                         {
7884                           exprNode_freeIniter (newel);
7885                         }
7886                     }
7887                 }
7888
7889               cstring_free (istring);
7890               i++;
7891               /*@-branchstate@*/ 
7892             } end_exprNodeList_elements;
7893           /*@=branchstate@*/
7894         }
7895       else if (ctype_isStruct (ctype_realType (t1)))
7896         {
7897           uentryList fields = ctype_getFields (t1);
7898           int i = 0;
7899
7900           if (uentryList_size (fields) != exprNodeList_size (vals))
7901             {
7902               if (uentryList_size (fields) > exprNodeList_size (vals))
7903                 {
7904                   hasError = optgenerror 
7905                     (FLG_FULLINITBLOCK,
7906                      message ("Initializer block for "
7907                               "%s has %d field%&, but %s has %d field%&: %q",
7908                               exprNode_unparse (el),
7909                               exprNodeList_size (vals),
7910                               ctype_unparse (t1),
7911                               uentryList_size (fields),
7912                               exprNodeList_unparse (vals)),
7913                      val->loc);   
7914                 }
7915               else
7916                 {
7917                   hasError = optgenerror 
7918                     (FLG_TYPE,
7919                      message ("Initializer block for "
7920                               "%s has %d field%&, but %s has %d field%&: %q",
7921                               exprNode_unparse (el),
7922                               exprNodeList_size (vals),
7923                               ctype_unparse (t1),
7924                               uentryList_size (fields),
7925                               exprNodeList_unparse (vals)),
7926                      val->loc);   
7927                 }
7928             }
7929           else
7930             {
7931               exprNodeList_elements (vals, oneval)
7932                 {
7933                   uentry thisfield = uentryList_getN (fields, i);
7934                   exprNode newel =
7935                     exprNode_fieldAccessAux (exprNode_fakeCopy (el),
7936                                              exprNode_loc (el),
7937                                              uentry_getName (thisfield));
7938
7939                   if (exprNode_isDefined (newel))
7940                     {
7941                       if (exprNode_checkOneInit (newel, oneval))
7942                         {
7943                           hasError = TRUE;
7944                         }
7945
7946                       exprNode_freeIniter (newel);
7947                     }
7948
7949                   i++;
7950                 } end_exprNodeList_elements;
7951             }
7952         }
7953       else
7954         {
7955           hasError = optgenerror 
7956             (FLG_TYPE,
7957              message ("Initializer block used for "
7958                       "%s where %t is expected: %s",
7959                       exprNode_unparse (el), t1, exprNode_unparse (val)),
7960              val->loc);   
7961         }
7962     }
7963   else
7964     {
7965       if (exprNode_isDefined (val))
7966         {
7967           doAssign (el, val, TRUE);
7968           
7969           if (!exprNode_matchType (t1, val))
7970             {
7971               hasError = gentypeerror 
7972                 (t1, val, t2, el,
7973                  message ("Initial value of %s is type %t, "
7974                           "expects %t: %s",
7975                           exprNode_unparse (el),
7976                           t2, t1, exprNode_unparse (val)),
7977                  val->loc);
7978             }
7979         }
7980     }
7981
7982   return hasError;
7983 }
7984
7985 static exprNode 
7986 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
7987 {
7988   exprNode ret;
7989
7990   if (usymtab_exists (idDecl_observeId (t)))
7991     {
7992       uentry ue = usymtab_lookup (idDecl_observeId (t));
7993       ret = exprNode_createId (ue);
7994
7995       /*@i723 don't do this...but why? */
7996 # if 0
7997       ct = ctype_realishType (ret->typ);
7998
7999       DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8000
8001       if (ctype_isUnknown (ct)) 
8002         {
8003           if (uentry_isAnyTag (ue))
8004             {
8005               voptgenerror
8006                 (FLG_IMPTYPE,
8007                  message ("%s used but not previously declared: %s",
8008                           uentry_ekindName (ue),
8009                           idDecl_getName (t)),
8010                  g_currentloc);
8011               
8012             }
8013           else
8014             {
8015               voptgenerror
8016                 (FLG_IMPTYPE,
8017                  message ("Variable has unknown (implicitly int) type: %s",
8018                           idDecl_getName (t)),
8019                  g_currentloc);
8020             }
8021
8022           ct = ctype_int;
8023         }
8024 # endif
8025     }
8026   else
8027     {
8028       uentry ue;
8029
8030       DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8031
8032       ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8033       /*!! fileloc_copy (g_currentloc)); */
8034       /*@i32!!! should get error without this */
8035       ret = exprNode_fromIdentifierAux (ue);
8036
8037       /*
8038       ** No error - this happens in old style declarations:
8039
8040       voptgenerror
8041         (FLG_UNRECOG,
8042          message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8043          g_currentloc);
8044
8045       ** 
8046       */
8047     }
8048
8049   exprData_free (ret->edata, ret->kind); 
8050   ret->edata = exprData_undefined;
8051
8052   ret->exitCode = XK_NEVERESCAPE;
8053   ret->mustBreak = FALSE;
8054   ret->kind = XPR_INIT;
8055   return ret;
8056 }
8057   
8058 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8059 {
8060   exprNode ret = exprNode_makeInitializationAux (t);
8061   llassert (ret->edata == exprData_undefined);
8062   ret->edata = exprData_makeInit (t, exprNode_undefined);
8063   return ret;
8064 }
8065
8066 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8067                                       /*@only@*/ exprNode e)
8068 {
8069   uentry ue = usymtab_lookup (idDecl_observeId (t));
8070   exprNode ret = exprNode_makeInitializationAux (t);
8071   fileloc loc = exprNode_loc (e);
8072   
8073   if (exprNode_isError (e)) 
8074     {
8075       e = exprNode_createUnknown ();
8076       idDecl_free (t);
8077
8078       /* error: assume initializer is defined */
8079       sRef_setDefined (ret->sref, g_currentloc); 
8080     }
8081   else
8082     {
8083       ctype ct = ctype_realishType (ret->typ);
8084
8085       /*
8086       ** evs - 9 Apr 1995
8087       **
8088       ** was addSafeUse --- what's the problem?
8089       **
8090       **   int x = 3, y = x ?
8091       */
8092
8093       exprData_free (ret->edata, ret->kind);
8094       ret->edata = exprData_makeInit (t, e);
8095
8096       exprNode_checkUse (ret, e->sref, e->loc);
8097       
8098       if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8099         {
8100           exprNode lhs = exprNode_createId (ue);
8101
8102           /*
8103           ** static storage should be undefined before initializing
8104           */
8105
8106           if (uentry_isStatic (ue))
8107             {
8108               sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8109             }
8110
8111           (void) exprNode_checkOneInit (lhs, e);
8112
8113           if (uentry_isStatic (ue))
8114             {
8115               sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8116             }
8117
8118           exprNode_free (lhs);
8119         }
8120       else
8121         {
8122           if (!exprNode_matchType (ct, e))
8123             {
8124               if (exprNode_isZero (e) && ctype_isArrayPtr (ct)) 
8125                 {
8126                   ;
8127                 }
8128               else
8129                 {
8130                   (void) gentypeerror 
8131                     (exprNode_getType (e), e, exprNode_getType (ret), ret,
8132                      message 
8133                      ("Variable %q initialized to type %t, expects %t: %s",
8134                       uentry_getName (ue), exprNode_getType (e), 
8135                       exprNode_getType (ret),
8136                       exprNode_unparse (e)),
8137                      e->loc);
8138                 }
8139             }
8140         }
8141       
8142       if (uentry_isStatic (ue))
8143         {
8144           sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8145         }
8146
8147       doAssign (ret, e, TRUE);
8148
8149       if (uentry_isStatic (ue))
8150         {
8151           sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8152         }
8153     }
8154
8155   if (context_inIterDef ())
8156     {
8157       /* should check if it is yield */
8158       uentry_setUsed (ue, loc);
8159     }
8160   else
8161     {
8162       ;
8163     }
8164
8165   exprNode_mergeUSs (ret, e);
8166   return ret;
8167 }
8168   
8169 exprNode exprNode_iter (/*@observer@*/ uentry name,
8170                         /*@only@*/ exprNodeList alist, 
8171                         /*@only@*/ exprNode body,
8172                         /*@observer@*/ uentry end)
8173 {
8174   exprNode ret;
8175   cstring iname;
8176
8177   llassert (uentry_isValid (name));
8178
8179   uentry_setUsed (name, exprNode_loc (body));
8180
8181   ret = exprNode_createPartialCopy (body);
8182   iname = uentry_getName (name);
8183
8184   if (uentry_isInvalid (end))
8185     {
8186       llerror (FLG_ITER,
8187                message ("Iter %s not balanced with end_%s", iname, iname));
8188     }
8189   else
8190     {
8191       cstring ename = uentry_getName (end);
8192
8193       if (!cstring_equalPrefixLit (ename, "end_"))
8194         {
8195           llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s", 
8196                                       iname, iname, ename));
8197         }
8198       else
8199         {
8200           if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8201             {
8202               llerror (FLG_ITER, 
8203                        message ("Iter %s not balanced with end_%s: %s", 
8204                                 iname, iname, ename));
8205             }
8206         }
8207
8208       cstring_free (ename);
8209     }
8210
8211   context_exitIterClause (body);
8212   
8213   ret->kind = XPR_ITER;
8214   ret->edata = exprData_makeIter (name, alist, body, end);
8215
8216   if (uentry_isIter (name))
8217     {
8218       (void) checkArgsReal (name, body, 
8219                             uentry_getParams (name), alist, TRUE, ret);
8220     }
8221
8222   cstring_free (iname);
8223
8224   return ret;
8225 }
8226
8227 exprNode
8228 exprNode_iterNewId (/*@only@*/ cstring s)
8229 {
8230   exprNode e = exprNode_new ();
8231   uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8232
8233   llassert (processingIterVars ());
8234
8235   e->loc = context_getSaveLocation ();
8236
8237   if (fileloc_isUndefined (e->loc))
8238     {
8239       fileloc_free (e->loc);
8240       e->loc = fileloc_copy (g_currentloc);
8241     }
8242
8243   e->uses = sRefSet_new ();
8244   e->sets = sRefSet_new ();
8245   e->msets = sRefSet_new ();
8246   e->kind = XPR_VAR;
8247   e->val = multiVal_unknown ();
8248   e->guards = guardSet_new ();
8249   e->sref = defref;
8250   e->isJumpPoint = FALSE;
8251   e->exitCode = XK_NEVERESCAPE;
8252
8253   /*> missing fields, detected by lclint <*/
8254   e->canBreak = FALSE;
8255   e->mustBreak = FALSE;
8256   e->etext = cstring_undefined;
8257
8258   if (uentry_isYield (ue))
8259     {
8260       uentry uue = uentry_makeVariable (s, uentry_getType (ue), 
8261                                         fileloc_copy (e->loc), 
8262                                         FALSE);
8263       sRef sr;
8264
8265       uue = usymtab_supEntrySrefReturn (uue);
8266
8267       sr = uentry_getSref (uue);
8268       sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8269       sr = uentry_getSref (uue);
8270       sRef_setDefined (sr, e->loc);
8271
8272       e->typ = uentry_getType (uue);      
8273       e->sref = sr;
8274       e->edata = exprData_makeId (uue);
8275       uentry_setUsed (uue, g_currentloc);
8276     }
8277   else
8278     {
8279       uentry uue;
8280
8281       sRef_setGlobalScope ();
8282       uue = uentry_makeVariableLoc (s, ctype_unknown);
8283
8284       e->typ = ctype_unknown;
8285       e->edata = exprData_makeId (uue);
8286
8287       uentry_setUsed (uue, e->loc);
8288       uentry_setHasNameError (uue); 
8289
8290       if (context_getFlag (FLG_REPEATUNRECOG))
8291         {
8292           uentry_markOwned (uue);
8293         }
8294       else
8295         {
8296           usymtab_supGlobalEntry (uue);      
8297         }
8298
8299       sRef_clearGlobalScope ();
8300
8301       voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8302                     e->loc);
8303     }
8304
8305
8306   cstring_free (s);
8307   
8308   exprNode_defineConstraints(e);
8309   return (e);
8310 }
8311
8312 exprNode
8313 exprNode_iterExpr (/*@returned@*/ exprNode e)
8314 {
8315   if (!processingIterVars ())
8316     {
8317       llcontbuglit ("checkIterParam: not in iter");
8318       return e;
8319     }
8320   
8321   if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()), 
8322                                        iterParamNo ())))
8323     {
8324       if (exprNode_isDefined (e))
8325         {
8326           if (fileloc_isDefined (e->loc))
8327             {
8328               voptgenerror
8329                 (FLG_ITER,
8330                  message ("Yield parameter is not simple identifier: %s", 
8331                           exprNode_unparse (e)),
8332                  e->loc);
8333             }
8334           else
8335             {
8336               voptgenerror
8337                 (FLG_ITER,
8338                  message ("Yield parameter is not simple identifier: %s",
8339                           exprNode_unparse (e)),
8340                  g_currentloc);
8341               
8342             }
8343         }
8344     }
8345   return e;
8346 }
8347
8348 exprNode
8349 exprNode_iterId (/*@observer@*/ uentry c)
8350 {
8351   uentry ue;
8352
8353   llassert (processingIterVars ());
8354
8355   ue = uentryList_getN (uentry_getParams (getCurrentIter ()), 
8356                         iterParamNo ());
8357
8358   if (uentry_isYield (ue))
8359     {
8360       ctype ct = uentry_getType (ue);
8361       exprNode e = exprNode_createPlain (ct);
8362       cstring name = uentry_getName (c);
8363       uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8364
8365       uentry_setUsed (ue, g_currentloc);
8366       uentry_setHasNameError (ue); 
8367       
8368       cstring_free (name);
8369       
8370       e->kind = XPR_VAR;
8371       e->edata = exprData_makeId (le);
8372       e->loc = context_getSaveLocation ();
8373       e->sref = uentry_getSref (le);
8374
8375       usymtab_supEntrySref (le);
8376
8377       if (!context_inHeader ())
8378         {
8379           if (optgenerror
8380               (FLG_ITER,
8381                message ("Yield parameter shadows local declaration: %q",
8382                         uentry_getName (c)),
8383                fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8384             {
8385               uentry_showWhereDeclared (c);
8386             }
8387         }
8388
8389       return e;
8390     }
8391
8392   return (exprNode_fromIdentifierAux (c));
8393 }
8394
8395 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8396 {
8397   exprNode ret = exprNode_create (ctype_unknown);
8398
8399   ret->kind = XPR_ITERCALL;
8400   ret->edata = exprData_makeIterCall (name, alist);
8401   
8402   if (uentry_isIter (name))
8403     {
8404       uentryList params = uentry_getParams (name);
8405
8406       if (context_inIterDef () 
8407           && uentryList_size (params) == exprNodeList_size (alist))
8408         {
8409           int i = 0;
8410           
8411           exprNodeList_elements (alist, arg)
8412             {
8413               uentry parg = uentryList_getN (params, i);
8414
8415               if (uentry_isYield (parg))
8416                 {
8417                   uentry ue = exprNode_getUentry (arg);
8418
8419                   if (uentry_isValid (ue))
8420                     {
8421                       ;
8422                     }
8423                 }
8424
8425               i++;
8426             } end_exprNodeList_elements;
8427         }
8428
8429       (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8430       checkUnspecCall (ret, params, alist);
8431     }
8432
8433   return ret;
8434 }
8435
8436 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8437 {
8438   if (exprNode_isDefined (e))
8439     {
8440       /*@access sRef@*/
8441       if (e->sref == defref) /*@noaccess sRef@*/
8442         {
8443           /*@-mods@*/
8444           e->sref = sRef_makeUnknown (); 
8445           sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8446           /*@=mods@*/
8447           return e->sref;
8448         }
8449       else
8450         {
8451           return e->sref;
8452         }
8453     }
8454   else
8455     {
8456       return sRef_undefined;
8457     }
8458 }
8459
8460 /*@observer@*/ cstring
8461 exprNode_unparseFirst (exprNode e)
8462 {
8463   if (exprNode_isDefined (e))
8464     {
8465       cstring ret;
8466
8467       if (e->kind == XPR_STMTLIST
8468           || e->kind == XPR_COMMA || e->kind == XPR_COND)
8469         {
8470           exprNode first = exprData_getPairA (e->edata);
8471
8472           if (exprNode_isDefined (first))
8473             {
8474               return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8475             }
8476           else
8477             {
8478               return (cstring_makeLiteralTemp ("..."));
8479             }
8480         }
8481
8482       ret = cstring_elide (exprNode_unparse (e), 20);
8483       cstring_markOwned (ret);
8484       
8485       return (ret);
8486     }
8487   else
8488     {
8489       return cstring_makeLiteralTemp ("<error>");
8490     }
8491 }
8492
8493 /*@observer@*/ cstring
8494 exprNode_unparse (/*@temp@*/ exprNode e)
8495 {
8496   if (exprNode_isError (e))
8497     {
8498       return cstring_makeLiteralTemp ("<error>");
8499     }
8500
8501   if (cstring_isDefined (e->etext))
8502     {
8503       return e->etext;
8504     }
8505   else
8506     {
8507       cstring ret = exprNode_doUnparse (e);
8508
8509       /*@-modifies@*/ /* benevolent */
8510       e->etext = ret; 
8511       /*@=modifies@*/
8512       return ret;
8513     }
8514 }
8515
8516 /*@observer@*/ fileloc
8517 exprNode_loc (exprNode e)
8518 {
8519   if (exprNode_isError (e))
8520     {
8521       return (g_currentloc);
8522     }
8523   else
8524     {
8525       return (e->loc);
8526     }
8527 }
8528
8529 /*
8530 ** executes exprNode e
8531 **    recursively rexecutes as though in original parse using
8532 **    information in e->edata
8533 */
8534
8535 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8536 {
8537   exprNodeList ret = exprNodeList_new ();
8538
8539   exprNodeList_elements (e, current)
8540     {
8541       exprNodeList_addh (ret, exprNode_effect (current));
8542     } end_exprNodeList_elements;
8543
8544   return ret;
8545 }
8546
8547 static /*@only@*/ exprNode exprNode_effect (exprNode e) 
8548    /*@globals internalState@*/
8549 {
8550   bool innerEffect = inEffect;
8551   exprNode ret;
8552   exprData data;
8553
8554   inEffect = TRUE;
8555
8556   context_clearJustPopped ();
8557
8558   if (exprNode_isError (e))
8559     {
8560       ret = exprNode_undefined;
8561     }
8562   else
8563     {
8564       /*
8565       ** Turn off expose and dependent transfer checking.
8566       ** Need to pass exposed internal nodes,
8567       ** [ copying would be a waste! ]
8568       ** [ Actually, I think I wasted a lot more time than its worth ]
8569       ** [ trying to do this. ]
8570       */
8571
8572       /*@-exposetrans@*/
8573       /*@-observertrans@*/
8574       /*@-dependenttrans@*/
8575       
8576       data = e->edata;
8577       
8578       switch (e->kind)
8579         {
8580         case XPR_PARENS: 
8581           ret = exprNode_addParens (exprData_getUopTok (data), 
8582                                     exprNode_effect (exprData_getUopNode (data)));
8583           break;
8584         case XPR_ASSIGN:
8585           ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)), 
8586                                  exprNode_effect (exprData_getOpB (data)), 
8587                                  exprData_getOpTok (data));
8588           break;
8589         case XPR_INITBLOCK:
8590           ret = exprNode_undefined;
8591           break;
8592         case XPR_CALL:
8593           ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8594                                        exprNodeList_effect (exprData_getArgs (data)));
8595           break;
8596         case XPR_EMPTY:
8597           ret = e;
8598           break;
8599
8600         case XPR_LABEL:
8601           ret = e;
8602           break;
8603
8604         case XPR_CONST:
8605         case XPR_VAR:
8606           {
8607             cstring id = exprData_getId (data);
8608             uentry ue = usymtab_lookupSafe (id);
8609
8610             ret = exprNode_fromIdentifierAux (ue);
8611             ret->loc = fileloc_update (ret->loc, e->loc);
8612             break;
8613           }
8614         case XPR_BODY:
8615           ret = e;
8616           break;
8617         case XPR_FETCH:
8618           ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)), 
8619                                      exprNode_effect (exprData_getPairB (data)));
8620           break;
8621         case XPR_OP:
8622           ret = exprNode_op (exprNode_effect (exprData_getOpA (data)), 
8623                              exprNode_effect (exprData_getOpB (data)), 
8624                              exprData_getOpTok (data));
8625           break;
8626           
8627         case XPR_POSTOP:
8628           ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)), 
8629                                  exprData_getUopTok (data));
8630           break;
8631         case XPR_PREOP:
8632           ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)), 
8633                                 exprData_getUopTok (data));
8634           break;
8635
8636         case XPR_OFFSETOF:
8637         case XPR_SIZEOFT:
8638         case XPR_SIZEOF:
8639         case XPR_ALIGNOFT:
8640         case XPR_ALIGNOF:
8641           ret = e;
8642           break;
8643           
8644         case XPR_VAARG:
8645           ret = exprNode_vaArg (exprData_getCastTok (data),
8646                                 exprNode_effect (exprData_getCastNode (data)),
8647                                 exprData_getCastType (data));
8648           break;
8649           
8650         case XPR_CAST:
8651           ret = exprNode_cast (exprData_getCastTok (data), 
8652                                exprNode_effect (exprData_getCastNode (data)), 
8653                                exprData_getCastType (data));
8654           break;
8655         case XPR_ITERCALL:
8656           ret = exprNode_iterStart (exprData_getIterCallIter (data),
8657                                     exprNodeList_effect 
8658                                     (exprData_getIterCallArgs (data)));
8659           break;
8660           
8661         case XPR_ITER:
8662           ret = exprNode_iter (exprData_getIterSname (data),
8663                                exprNodeList_effect (exprData_getIterAlist (data)),
8664                                exprNode_effect (exprData_getIterBody (data)),
8665                                exprData_getIterEname (data));
8666           break;
8667           
8668         case XPR_FOR:
8669           ret = exprNode_for (exprNode_effect (exprData_getPairA (data)), 
8670                               exprNode_effect (exprData_getPairB (data)));
8671           break;
8672           
8673         case XPR_FORPRED:
8674           ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8675                                   exprNode_effect (exprData_getTripleTest (data)),
8676                                   exprNode_effect (exprData_getTripleInc (data)));
8677           break;
8678           
8679         case XPR_TOK:
8680           ret = exprNode_createTok (exprData_getTok (data));
8681           break;
8682           
8683         case XPR_GOTO:
8684           ret = exprNode_goto (exprData_getLiteral (data));
8685           ret->loc = fileloc_update (ret->loc, e->loc);
8686           break;
8687           
8688         case XPR_CONTINUE:
8689           ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8690           break;
8691           
8692         case XPR_BREAK:
8693           ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8694           break;
8695           
8696         case XPR_RETURN:
8697           ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8698           break;
8699           
8700         case XPR_NULLRETURN:
8701           ret = exprNode_nullReturn (exprData_getTok (data));
8702           break;
8703           
8704         case XPR_COMMA:
8705           ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8706                                 exprNode_effect (exprData_getPairB (data)));
8707           break;
8708           
8709         case XPR_COND:
8710           ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8711                                exprNode_effect (exprData_getTripleTrue (data)),
8712                                exprNode_effect (exprData_getTripleFalse (data)));
8713           break;
8714         case XPR_IF:
8715           ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8716                              exprNode_effect (exprData_getPairB (data)));
8717           break;
8718           
8719         case XPR_IFELSE:
8720           ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8721                                  exprNode_effect (exprData_getTripleTrue (data)),
8722                                  exprNode_effect (exprData_getTripleFalse (data)));
8723           break;
8724         case XPR_WHILEPRED:
8725           ret = exprNode_whilePred (exprData_getSingle (data));
8726           break;
8727           
8728         case XPR_WHILE:
8729           ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8730                                 exprNode_effect (exprData_getPairB (data)));
8731           break;
8732           
8733         case XPR_DOWHILE:
8734           ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8735                                   exprNode_effect (exprData_getPairB (data)));
8736           break;
8737
8738         case XPR_BLOCK:
8739           ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8740           break;          
8741
8742         case XPR_STMT:
8743           ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8744                                     exprData_getUopTok (data));
8745           break;
8746           
8747         case XPR_STMTLIST:
8748           ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8749                                  exprNode_effect (exprData_getPairB (data)));
8750           break;
8751           
8752         case XPR_FTCASE:
8753         case XPR_CASE:
8754           ret = exprNode_caseMarker 
8755             (exprNode_effect (exprData_getSingle (data)),
8756              TRUE);
8757           break;
8758           
8759         case XPR_FTDEFAULT:
8760         case XPR_DEFAULT:
8761           ret = exprNode_createTok (exprData_getTok (data));
8762           break;
8763           
8764         case XPR_SWITCH:
8765           ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8766                                  exprNode_effect (exprData_getPairB (data)));
8767           break;
8768           
8769         case XPR_INIT:
8770           ret = exprNode_makeInitialization
8771             (exprData_getInitId (data),
8772              exprNode_effect (exprData_getInitNode (data)));
8773           break;
8774           
8775         case XPR_FACCESS:
8776           ret = exprNode_fieldAccessAux
8777             (exprNode_effect (exprData_getFieldNode (data)),
8778              exprNode_loc (exprData_getFieldNode (data)),
8779              cstring_copy (exprData_getFieldName (data)));
8780           break;
8781           
8782         case XPR_ARROW:
8783           ret = exprNode_arrowAccessAux
8784             (exprNode_effect (exprData_getFieldNode (data)),
8785              exprNode_loc (exprData_getFieldNode (data)),
8786              cstring_copy (exprData_getFieldName (data)));
8787           break;
8788           
8789         case XPR_STRINGLITERAL:
8790           ret = e;
8791           break;
8792           
8793         case XPR_NUMLIT:
8794           ret = e;
8795           break;
8796
8797         case XPR_NODE:
8798           ret = e;
8799           break;
8800           /*@-branchstate@*/ 
8801         } 
8802       /*@=branchstate@*/
8803       /*@=observertrans@*/
8804       /*@=exposetrans@*/
8805       /*@=dependenttrans@*/
8806     }
8807
8808   if (!innerEffect) 
8809     {
8810       inEffect = FALSE;
8811     }
8812
8813   return ret;
8814 }
8815
8816 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8817 {
8818   cstring ret;
8819   exprData data;
8820
8821   if (exprNode_isError (e))
8822     {
8823       return cstring_undefined;
8824     }
8825
8826   data = e->edata;
8827
8828   switch (e->kind)
8829     {
8830     case XPR_PARENS: 
8831       ret = exprNode_rootVarName (exprData_getUopNode (data));
8832       break;
8833     case XPR_ASSIGN:
8834       ret = exprNode_rootVarName (exprData_getOpA (data));
8835       break;
8836     case XPR_CONST:
8837     case XPR_VAR:
8838       ret = exprData_getId (data);
8839       break;
8840     case XPR_INIT:
8841       ret = idDecl_getName (exprData_getInitId (data));
8842       break;
8843     case XPR_LABEL:
8844     case XPR_TOK:
8845     case XPR_ITERCALL:
8846     case XPR_EMPTY:
8847     case XPR_CALL:
8848     case XPR_INITBLOCK:
8849     case XPR_BODY:
8850     case XPR_FETCH:
8851     case XPR_OP:
8852     case XPR_POSTOP:
8853     case XPR_PREOP:
8854     case XPR_OFFSETOF:
8855     case XPR_ALIGNOFT:
8856     case XPR_ALIGNOF:
8857     case XPR_SIZEOFT:
8858     case XPR_SIZEOF:
8859     case XPR_VAARG:
8860     case XPR_CAST:
8861     case XPR_ITER:
8862     case XPR_FOR:
8863     case XPR_FORPRED:
8864     case XPR_BREAK:
8865     case XPR_RETURN:
8866     case XPR_NULLRETURN:
8867     case XPR_COMMA:
8868     case XPR_COND:
8869     case XPR_IF:
8870     case XPR_IFELSE:
8871     case XPR_WHILE:
8872     case XPR_WHILEPRED:
8873     case XPR_DOWHILE:
8874     case XPR_GOTO:
8875     case XPR_CONTINUE:
8876     case XPR_FTDEFAULT:
8877     case XPR_DEFAULT:
8878     case XPR_SWITCH:
8879     case XPR_FTCASE:
8880     case XPR_CASE:
8881     case XPR_BLOCK:
8882     case XPR_STMT:
8883     case XPR_STMTLIST:
8884     case XPR_FACCESS:
8885     case XPR_ARROW:
8886     case XPR_NODE:
8887     case XPR_NUMLIT:
8888     case XPR_STRINGLITERAL:
8889       ret = cstring_undefined;
8890       break;
8891     }
8892
8893   return ret;
8894 }
8895
8896 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8897 {
8898   cstring ret;
8899   exprData data;
8900
8901   if (exprNode_isError (e))
8902     {
8903       static /*@only@*/ cstring error = cstring_undefined;
8904
8905       if (!cstring_isDefined (error))
8906         {
8907           error = cstring_makeLiteral ("<error>");
8908         }
8909       
8910       return error;
8911     }
8912
8913   data = e->edata;
8914
8915   switch (e->kind)
8916     {
8917     case XPR_PARENS: 
8918       ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8919       break;
8920     case XPR_ASSIGN:
8921       ret = message ("%s %s %s",
8922                      exprNode_unparse (exprData_getOpA (data)), 
8923                      lltok_unparse (exprData_getOpTok (data)),
8924                      exprNode_unparse (exprData_getOpB (data)));
8925       break;
8926     case XPR_CALL:
8927       ret = message ("%s(%q)",
8928                      exprNode_unparse (exprData_getFcn (data)), 
8929                      exprNodeList_unparse (exprData_getArgs (data)));
8930       break;
8931     case XPR_INITBLOCK:
8932       ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8933       break;
8934     case XPR_EMPTY:
8935       ret = cstring_undefined;
8936       break;
8937     case XPR_LABEL:
8938       ret = message ("%s:", exprData_getId (data));
8939       break;
8940     case XPR_CONST:
8941     case XPR_VAR:
8942       ret = cstring_copy (exprData_getId (data));
8943       break;
8944     case XPR_FETCH:
8945       ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8946                      exprNode_unparse (exprData_getPairB (data)));
8947       break;
8948     case XPR_BODY:
8949       ret = message ("<body>");
8950       break;
8951     case XPR_OP:
8952       ret = message ("%s %s %s",
8953                      exprNode_unparse (exprData_getOpA (data)), 
8954                      lltok_unparse (exprData_getOpTok (data)),
8955                      exprNode_unparse (exprData_getOpB (data))); 
8956       break;
8957       
8958     case XPR_PREOP: 
8959       ret = message ("%s%s",
8960                      lltok_unparse (exprData_getUopTok (data)),
8961                      exprNode_unparse (exprData_getUopNode (data))); 
8962       break;
8963
8964     case XPR_POSTOP:
8965       ret = message ("%s%s",
8966                      exprNode_unparse (exprData_getUopNode (data)),
8967                      lltok_unparse (exprData_getUopTok (data))); 
8968       break;
8969       
8970     case XPR_OFFSETOF:
8971       ret = message ("offsetof(%s,%q)", 
8972                      ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8973                      cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8974       break;
8975
8976     case XPR_SIZEOFT:
8977       ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8978       break;
8979       
8980     case XPR_SIZEOF:
8981       ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8982       break;
8983
8984     case XPR_ALIGNOFT:
8985       ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8986       break;
8987       
8988     case XPR_ALIGNOF:
8989       ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8990       break;
8991       
8992     case XPR_VAARG:
8993       ret = message ("va_arg(%s, %q)", 
8994                      exprNode_unparse (exprData_getCastNode (data)),
8995                      qtype_unparse (exprData_getCastType (data)));
8996       break;
8997       
8998     case XPR_ITERCALL:
8999       ret = message ("%q(%q)", 
9000                      uentry_getName (exprData_getIterCallIter (data)),
9001                      exprNodeList_unparse (exprData_getIterCallArgs (data)));
9002       break;
9003     case XPR_ITER:
9004       ret = message ("%q(%q) %s %q",
9005                      uentry_getName (exprData_getIterSname (data)),
9006                      exprNodeList_unparse (exprData_getIterAlist (data)),
9007                      exprNode_unparse (exprData_getIterBody (data)),
9008                      uentry_getName (exprData_getIterEname (data)));
9009       break;
9010     case XPR_CAST:
9011       ret = message ("(%q)%s", 
9012                      qtype_unparse (exprData_getCastType (data)),
9013                      exprNode_unparse (exprData_getCastNode (data)));
9014       break;
9015       
9016     case XPR_FOR:
9017       ret = message ("%s %s", 
9018                      exprNode_unparse (exprData_getPairA (data)), 
9019                      exprNode_unparse (exprData_getPairB (data)));
9020       break;
9021
9022     case XPR_FORPRED:
9023             ret = message ("for (%s; %s; %s)",
9024                      exprNode_unparse (exprData_getTripleInit (data)),
9025                      exprNode_unparse (exprData_getTripleTest (data)),
9026                      exprNode_unparse (exprData_getTripleInc (data)));
9027       break;
9028       
9029     case XPR_GOTO:
9030       ret = message ("goto %s", exprData_getLiteral (data));
9031       break;
9032
9033     case XPR_CONTINUE:
9034       ret = cstring_makeLiteral ("continue");
9035       break;
9036
9037     case XPR_BREAK:
9038       ret = cstring_makeLiteral ("break");
9039       break;
9040
9041     case XPR_RETURN:
9042       ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9043       break;
9044
9045     case XPR_NULLRETURN:
9046       ret = cstring_makeLiteral ("return");
9047       break;
9048
9049     case XPR_COMMA:
9050       ret = message ("%s, %s", 
9051                      exprNode_unparse (exprData_getPairA (data)),
9052                      exprNode_unparse (exprData_getPairB (data)));
9053       break;
9054       
9055     case XPR_COND:
9056       ret = message ("%s ? %s : %s",
9057                      exprNode_unparse (exprData_getTriplePred (data)),
9058                      exprNode_unparse (exprData_getTripleTrue (data)),
9059                      exprNode_unparse (exprData_getTripleFalse (data)));
9060       break;
9061     case XPR_IF:
9062       ret = message ("if (%s) %s", 
9063                      exprNode_unparse (exprData_getPairA (data)),
9064                      exprNode_unparse (exprData_getPairB (data)));
9065       break;
9066       
9067     case XPR_IFELSE:
9068       ret = message ("if (%s) %s else %s",
9069                      exprNode_unparse (exprData_getTriplePred (data)),
9070                      exprNode_unparse (exprData_getTripleTrue (data)),
9071                      exprNode_unparse (exprData_getTripleFalse (data)));
9072       break;
9073     case XPR_WHILE:
9074       ret = message ("while (%s) %s",
9075                      exprNode_unparse (exprData_getPairA (data)),
9076                      exprNode_unparse (exprData_getPairB (data)));
9077       break;
9078
9079     case XPR_WHILEPRED:
9080       ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9081       break;
9082
9083     case XPR_TOK:
9084       ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9085       break;
9086
9087     case XPR_DOWHILE:
9088       ret = message ("do { %s } while (%s)",
9089                      exprNode_unparse (exprData_getPairB (data)),
9090                      exprNode_unparse (exprData_getPairA (data)));
9091       break;
9092       
9093     case XPR_BLOCK:
9094       ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9095       break;
9096
9097     case XPR_STMT:
9098       ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9099       break;
9100
9101     case XPR_STMTLIST:
9102       ret = message ("%s; %s", 
9103                      exprNode_unparse (exprData_getPairA (data)),
9104                      exprNode_unparse (exprData_getPairB (data)));
9105       break;
9106       
9107     case XPR_FTDEFAULT:
9108     case XPR_DEFAULT:
9109       ret = cstring_makeLiteral ("default:");
9110       break;
9111
9112     case XPR_SWITCH:
9113       ret = message ("switch (%s) %s", 
9114                      exprNode_unparse (exprData_getPairA (data)),
9115                      exprNode_unparse (exprData_getPairB (data)));
9116       break;
9117
9118     case XPR_FTCASE:
9119     case XPR_CASE:
9120       ret = message ("case %s:", 
9121                      exprNode_unparse (exprData_getSingle (data)));
9122       break;
9123       
9124     case XPR_INIT:
9125       if (exprNode_isError (exprData_getInitNode (data)))
9126         {
9127           ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9128         }
9129       else
9130         {
9131           ret = message ("%q = %s",
9132                          idDecl_unparseC (exprData_getInitId (data)),
9133                          exprNode_unparse (exprData_getInitNode (data)));
9134         }
9135       break;
9136       
9137     case XPR_FACCESS:
9138       ret = message ("%s.%s",
9139                      exprNode_unparse (exprData_getFieldNode (data)),
9140                      exprData_getFieldName (data));
9141       break;
9142       
9143     case XPR_ARROW:
9144             ret = message ("%s->%s",
9145                      exprNode_unparse (exprData_getFieldNode (data)),
9146                      exprData_getFieldName (data));
9147       break;
9148
9149     case XPR_STRINGLITERAL:
9150       ret = message ("\"%s\"", exprData_getLiteral (data));
9151       break;
9152
9153     case XPR_NUMLIT:
9154       ret = cstring_copy (exprData_getLiteral (data));
9155       break;
9156
9157     case XPR_NODE:
9158       ret = cstring_makeLiteral ("<node>");
9159       break;
9160     }
9161
9162   return ret;
9163 }
9164
9165 bool
9166 exprNode_isInitializer (exprNode e)
9167 {
9168   return (exprNode_isDefined (e)
9169           && e->kind == XPR_INIT);
9170 }
9171
9172 bool 
9173 exprNode_isCharLit (exprNode e)
9174 {
9175   if (exprNode_isDefined (e))
9176     {
9177       return (multiVal_isChar (exprNode_getValue (e)));
9178     }
9179   else
9180     {
9181       return FALSE;
9182     }
9183 }
9184
9185 bool
9186 exprNode_isNumLit (exprNode e)
9187 {
9188   if (exprNode_isDefined (e))
9189     {
9190       return (multiVal_isInt (exprNode_getValue (e)));
9191     }
9192   else
9193     {
9194       return FALSE;
9195     }
9196 }
9197
9198 static bool
9199 exprNode_isFalseConstant (exprNode e)
9200 {
9201   if (exprNode_isDefined (e))
9202     {
9203       cstring s = exprNode_rootVarName (e);
9204
9205       if (cstring_equal (s, context_getFalseName ()))
9206         {
9207           return TRUE;
9208         }
9209     }
9210
9211   return FALSE;
9212 }
9213
9214 bool
9215 exprNode_matchLiteral (ctype expected, exprNode e)
9216 {
9217   if (exprNode_isDefined (e))
9218     {
9219       multiVal m = exprNode_getValue (e);
9220       
9221       if (multiVal_isDefined (m))
9222         {
9223           if (multiVal_isInt (m))
9224             {
9225               long int val = multiVal_forceInt (m);
9226               
9227               if (ctype_isDirectBool (ctype_realishType (expected)))
9228                 {
9229                   if (val == 0) 
9230                     {
9231                       return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9232                     }
9233                   else 
9234                     {
9235                       return FALSE;
9236                     }
9237                 }
9238               
9239               if (ctype_isRealInt (expected))
9240                 {
9241                   /*
9242                   ** unsigned <- [ constant >= 0 is okay ]
9243                   */
9244                   
9245                   if (ctype_isUnsigned (expected))
9246                     {
9247                       if (val < 0)
9248                         {
9249                           return FALSE;
9250                         }
9251                     }
9252                   
9253                   /*
9254                   ** No checks on sizes of integers...maybe add
9255                   ** these later.
9256                   */
9257
9258                   DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9259                   DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9260                             bool_unparse (ctype_isInt (exprNode_getType (e)))));
9261
9262                   if (context_getFlag (FLG_NUMLITERAL) 
9263                       && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9264                     return TRUE;
9265                   } else {
9266                     if (val == 0) {
9267                       return TRUE;
9268                     } else {
9269                       return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9270                     }
9271                   }
9272                 }
9273               else if (ctype_isChar (expected))
9274                 {
9275                   return FALSE;
9276                 }
9277               else if (ctype_isArrayPtr (expected))
9278                 {
9279                   return (val == 0);
9280                 }
9281               else if (ctype_isAnyFloat (expected))
9282                 {
9283                   return (context_getFlag (FLG_NUMLITERAL));
9284                 }
9285               else
9286                 {
9287                   return FALSE;
9288                 }
9289             }
9290           else if (multiVal_isDouble (m))
9291             {
9292               if (ctype_isAnyFloat (expected))
9293                 {
9294                   return TRUE;
9295                 }
9296             }
9297           else if (multiVal_isChar (m))
9298             {
9299               char val = multiVal_forceChar (m);          
9300               
9301               if (ctype_isChar (expected))
9302                 {
9303                   if (ctype_isUnsigned (expected) && ((int)val) < 0)
9304                     {
9305                       return FALSE;
9306                     }
9307                   else
9308                     {
9309                       return TRUE;
9310                     }
9311                 }
9312             }
9313           else
9314             {
9315               return FALSE;
9316             }
9317         }
9318     }
9319   
9320   return FALSE;
9321 }
9322
9323 bool
9324 exprNode_matchType (ctype expected, exprNode e)
9325 {
9326   ctype actual;
9327   
9328   if (!exprNode_isDefined (e)) return TRUE;
9329
9330   actual = ctype_realishType (exprNode_getType (e));
9331
9332   if (ctype_match (ctype_realishType (expected), actual))
9333     {
9334       return TRUE;
9335     }
9336
9337   llassert (!exprNode_isError (e));
9338   return (exprNode_matchLiteral (expected, e));
9339 }
9340
9341 static bool
9342 exprNode_matchTypes (exprNode e1, exprNode e2)
9343 {
9344   ctype t1;
9345   ctype t2;
9346  
9347   if (!exprNode_isDefined (e1)) return TRUE;
9348   if (!exprNode_isDefined (e2)) return TRUE;
9349
9350   /*
9351   ** realish type --- keep bools, bools 
9352   */ 
9353
9354   t1 = ctype_realishType (exprNode_getType (e1));
9355   t2 = ctype_realishType (exprNode_getType (e2));
9356
9357   if (ctype_match (t1, t2)) 
9358     {
9359       return TRUE;
9360     }
9361
9362   return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9363 }
9364
9365 /*
9366 ** pass e as ct
9367 */
9368
9369 static bool
9370   exprNode_matchArgType (ctype ct, exprNode e)
9371 {
9372   ctype et;
9373
9374   if (!exprNode_isDefined (e))
9375     {
9376       return TRUE;
9377     }
9378
9379   et = ctype_realType (exprNode_getType (e));
9380
9381   if (ctype_matchArg (ct, et)) return TRUE;
9382   
9383   llassert (!exprNode_isError (e));
9384   return (exprNode_matchLiteral (ct, e));
9385 }
9386
9387 static /*@only@*/ exprNodeSList
9388   exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9389 {
9390   if (exprNode_isDefined (e))
9391     {
9392       if (e->kind == XPR_STMTLIST)
9393         {
9394           return (exprNodeSList_append
9395                   (exprNode_flatten (exprData_getPairA (e->edata)),
9396                    exprNode_flatten (exprData_getPairB (e->edata))));
9397         }
9398       else if (e->kind == XPR_BLOCK)
9399         {
9400           return (exprNode_flatten (exprData_getSingle (e->edata)));
9401         }
9402       else
9403         {
9404           return (exprNodeSList_singleton (e));
9405         }
9406     }
9407
9408   return exprNodeSList_new ();
9409 }
9410
9411 static /*@exposed@*/ exprNode
9412 exprNode_lastStatement (/*@returned@*/ exprNode e)
9413 {
9414   if (exprNode_isDefined (e))
9415     {
9416       if (e->kind == XPR_STMTLIST)
9417         {
9418           exprNode b = exprData_getPairB (e->edata);
9419
9420           if (exprNode_isDefined (b))
9421             {
9422               return exprNode_lastStatement (b);
9423             }
9424           else
9425             {
9426               return exprNode_lastStatement (exprData_getPairA (e->edata));
9427             }
9428         }
9429       else if (e->kind == XPR_BLOCK)
9430         {
9431           return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9432         }
9433       else
9434         {
9435           return (e);
9436         }
9437     }
9438
9439   return exprNode_undefined;
9440 }
9441
9442 static /*@exposed@*/ exprNode
9443 exprNode_firstStatement (/*@returned@*/ exprNode e)
9444 {
9445   if (exprNode_isDefined (e))
9446     {
9447       if (e->kind == XPR_STMTLIST)
9448         {
9449           exprNode b = exprData_getPairA (e->edata);
9450
9451           if (exprNode_isDefined (b))
9452             {
9453               return exprNode_firstStatement (b);
9454             }
9455           else
9456             {
9457               return exprNode_firstStatement (exprData_getPairB (e->edata));
9458             }
9459         }
9460       else if (e->kind == XPR_BLOCK)
9461         {
9462           return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9463         }
9464       else
9465         {
9466           return (e);
9467         }
9468     }
9469
9470   return exprNode_undefined;
9471 }
9472   
9473 static void
9474 exprNode_mergeUSs (exprNode res, exprNode other)
9475 {
9476   if (exprNode_isDefined (res) && exprNode_isDefined (other))
9477     {
9478       res->msets = sRefSet_union (res->msets, other->msets);
9479       res->sets = sRefSet_union (res->sets, other->sets);
9480       res->uses = sRefSet_union (res->uses, other->uses);
9481     }
9482 }
9483
9484 static void
9485 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9486 {
9487   if (exprNode_isDefined (res))
9488     {
9489       if (exprNode_isDefined (other1))
9490         {
9491           res->sets = sRefSet_union (res->sets, other1->sets);
9492           res->msets = sRefSet_union (res->msets, other1->msets);
9493           res->uses = sRefSet_union (res->uses, other1->uses);
9494         }
9495       if (exprNode_isDefined (other2))
9496         {
9497           res->sets = sRefSet_union (res->sets, other2->sets);
9498           res->msets = sRefSet_union (res->msets, other2->msets);
9499           res->uses = sRefSet_union (res->uses, other2->uses);
9500         }
9501     }
9502 }
9503
9504 /*
9505 ** modifies e->uses
9506 **
9507 ** Reports errors is s is not defined.
9508 */
9509
9510 static void
9511 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9512 {
9513   if (exprNode_isDefined (e))
9514     {
9515       e->uses = sRefSet_insert (e->uses, s);
9516     }
9517 }
9518   
9519 void
9520 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9521 {
9522   if (sRef_isKnown (s) && !sRef_isConst (s))
9523     {
9524       /*
9525       ** need to check all outer types are useable
9526       */
9527
9528       DPRINTF (("Check use: %s / %s",
9529                 exprNode_unparse (e), sRef_unparse (s)));
9530       
9531       exprNode_addUse (e, s);
9532      
9533       if (!context_inProtectVars ())
9534         {
9535           /*
9536           ** only report the deepest error
9537           */
9538           
9539           sRef errorRef = sRef_undefined;
9540           sRef lastRef  = sRef_undefined;
9541           bool deadRef = FALSE;
9542           bool unuseable = FALSE;
9543           bool errorMaybe = FALSE;
9544           
9545           while (sRef_isValid (s) && sRef_isKnown (s))
9546             {
9547               ynm readable = sRef_isReadable (s);
9548
9549               DPRINTF (("Readable: %s / %s",
9550                         sRef_unparseFull (s), ynm_unparse (readable)));
9551
9552               if (!(ynm_toBoolStrict (readable)))
9553                 {
9554                   if (ynm_isMaybe (readable))
9555                     {
9556                       lastRef = errorRef;
9557                       errorRef = s;
9558                       DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
9559                       deadRef = sRef_isPossiblyDead (errorRef);
9560                       unuseable = sRef_isUnuseable (errorRef);
9561                       errorMaybe = TRUE;
9562                     }
9563                   else
9564                     {
9565                       lastRef = errorRef;
9566                       errorRef = s;
9567                       deadRef = sRef_isDead (errorRef);
9568                       unuseable = sRef_isUnuseable (errorRef);
9569                       errorMaybe = FALSE;
9570                     }
9571
9572                   if (!sRef_isPartial (s))
9573                     {
9574                       DPRINTF (("Defining! %s", sRef_unparseFull (s)));
9575                       sRef_setDefined (s, fileloc_undefined);
9576                     }
9577                 }
9578
9579               s = sRef_getBaseSafe (s);
9580             } /* end while */
9581           
9582           if (sRef_isValid (errorRef)) 
9583             {
9584               if (sRef_isValid (lastRef) && sRef_isField (lastRef) 
9585                   && sRef_isPointer (errorRef))
9586                 {
9587                   errorRef = lastRef;
9588                 }
9589               
9590               if (deadRef)
9591                 {
9592                   if (sRef_isThroughArrayFetch (errorRef))
9593                     {
9594                       if (optgenerror 
9595                           (FLG_STRICTUSERELEASED,
9596                            message ("%q %q may be used after being released", 
9597                                     sRef_unparseKindNamePlain (errorRef),
9598                                     sRef_unparse (errorRef)),
9599                            loc))
9600                         {
9601                           sRef_showRefKilled (errorRef);
9602                           
9603                           if (sRef_isKept (errorRef))
9604                             {
9605                               sRef_clearAliasState (errorRef, loc);
9606                             }
9607                         }
9608                     }
9609                   else
9610                     {
9611                       DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9612
9613                       if (optgenerror
9614                           (FLG_USERELEASED,
9615                            message ("%q %q %qused after being released", 
9616                                     sRef_unparseKindNamePlain (errorRef),
9617                                     sRef_unparse (errorRef),
9618                                     cstring_makeLiteral (errorMaybe 
9619                                                          ? "may be " : "")),
9620                            loc))
9621                         {
9622                           sRef_showRefKilled (errorRef);
9623                           
9624                           if (sRef_isKept (errorRef))
9625                             {
9626                               sRef_clearAliasState (errorRef, loc);
9627                             }
9628                         }
9629                     }
9630                 }
9631               else if (unuseable)
9632                 {
9633                   if (optgenerror
9634                       (FLG_USEDEF,
9635                        message ("%q %q%qused in inconsistent state", 
9636                                 sRef_unparseKindName (errorRef),
9637                                 sRef_unparseOpt (errorRef),
9638                                 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9639                        loc))
9640                     {
9641                       sRef_showStateInconsistent (errorRef);
9642                     }
9643                 }
9644               else
9645                 {
9646                   DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
9647
9648                   voptgenerror 
9649                     (FLG_USEDEF,
9650                      message ("%q %q%qused before definition", 
9651                               sRef_unparseKindName (errorRef),
9652                               sRef_unparseOpt (errorRef),
9653                               cstring_makeLiteral (errorMaybe ? "may be " : "")),
9654                      loc);
9655
9656                   DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
9657                 }
9658               
9659               sRef_setDefined (errorRef, loc);
9660           
9661               if (sRef_isAddress (errorRef))
9662                 {
9663                   sRef_setDefined (sRef_getRootBase (errorRef), loc);
9664                 }
9665             } /* end is error */
9666         }
9667     }
9668
9669   setCodePoint ();
9670 }
9671
9672 static void
9673 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
9674 {
9675   if (exprNode_isDefined (e) && sRef_isKnown (s))
9676     {
9677       e->uses = sRefSet_insert (e->uses, s);
9678     }
9679 }
9680
9681 static void
9682 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9683 {
9684   if (exprNode_isDefined (e))
9685     {
9686       e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9687     }
9688 }
9689
9690 void
9691 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
9692 {
9693   sRef defines = sRef_undefined;
9694
9695   if (sRef_isValid (s) && !sRef_isNothing (s))
9696     {
9697       uentry ue = sRef_getBaseUentry (s);
9698
9699       if (uentry_isValid (ue))
9700         {
9701           uentry_setLset (ue);
9702         }
9703
9704       if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9705         {
9706           voptgenerror (FLG_USEDEF,
9707                         message ("Attempt to set unuseable storage: %q", 
9708                                  sRef_unparse (s)),
9709                         exprNode_loc (e));
9710         }
9711      
9712       if (sRef_isMeaningful (s))
9713         {         
9714           if (sRef_isDead (s))
9715             {
9716               sRef base = sRef_getBaseSafe (s);
9717
9718               if (sRef_isValid (base) 
9719                   && sRef_isDead (base))
9720                 {
9721                   sRef_setPartial (s, exprNode_loc (e));
9722                 }
9723               
9724               defines = s; /* okay - modifies for only param */
9725             }
9726           else if (sRef_isPartial (s))
9727             {
9728               sRef eref = exprNode_getSref (e);
9729
9730               if (!sRef_isPartial (eref))
9731                 {
9732                   /*
9733                   ** should do something different here???
9734                   */
9735                   
9736                   sRef_setDefinedComplete (eref, exprNode_loc (e));               
9737                 }
9738               else
9739                 {
9740                   sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9741                 }
9742
9743               if (sRef_isMeaningful (eref))
9744                 {
9745                   defines = eref;
9746                 }
9747               else
9748                 {                
9749                   defines = s;
9750                 }
9751             }
9752           else if (sRef_isAllocated (s))
9753             {
9754               sRef eref = exprNode_getSref (e);
9755
9756               
9757               if (!sRef_isAllocated (eref))
9758                 {
9759                   sRef_setDefinedComplete (eref, exprNode_loc (e));
9760                 }
9761               else
9762                 {
9763                   sRef base = sRef_getBaseSafe (eref);
9764                   
9765                   if (sRef_isValid (base))
9766                     {
9767                       sRef_setPdefined (base, exprNode_loc (e)); 
9768                     }
9769                 }
9770
9771               defines = s;
9772             }
9773           else 
9774             {
9775               sRef_setDefinedNCComplete (s, exprNode_loc (e));
9776               defines = s;
9777             }
9778
9779         }
9780       else /* not meaningful...but still need to insert it */
9781         {
9782           defines = s;
9783         }
9784     }
9785
9786   if (exprNode_isDefined (e) && sRef_isValid (defines))
9787     {
9788       e->sets = sRefSet_insert (e->sets, defines); 
9789     }
9790 }
9791
9792 void
9793 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
9794 {
9795   if (sRef_isValid (s) && !sRef_isNothing (s))
9796     {
9797       uentry ue = sRef_getBaseUentry (s);
9798
9799       if (uentry_isValid (ue))
9800         {
9801           uentry_setLset (ue);
9802         }
9803
9804       if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9805         {
9806           voptgenerror (FLG_USEDEF,
9807                         message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9808                         exprNode_loc (e));
9809         }
9810       
9811       if (sRef_isMeaningful (s))
9812         {
9813           sRef_setDefinedComplete (s, exprNode_loc (e));
9814         }
9815       
9816       if (exprNode_isDefined (e))
9817         {
9818           e->msets = sRefSet_insert (e->msets, s);
9819         }
9820     }
9821 }
9822
9823 static void
9824 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9825 {
9826   checkAnyCall (fcn, cstring_undefined, params, args, 
9827                 FALSE, sRefSet_undefined, FALSE, 0);
9828 }
9829
9830 static void
9831 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current, 
9832              /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9833 {
9834   setCodePoint ();
9835   
9836   if (uentry_isYield (ucurrent))
9837     {
9838       sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9839       exprNode_checkSet (current, current->sref);
9840     }
9841   else 
9842     {
9843       if (uentry_isSefParam (ucurrent))
9844         {
9845           sRefSet sets = current->sets;
9846           sRef ref = exprNode_getSref (current);
9847
9848           if (sRef_isMacroParamRef (ref))
9849             {
9850               uentry ue = sRef_getUentry (ref);
9851
9852               if (!uentry_isSefParam (ue))
9853                 {
9854                   voptgenerror 
9855                     (FLG_SEFPARAMS,
9856                      message
9857                      ("Parameter %d to %s is declared sef, but "
9858                       "the argument is a macro parameter declared "
9859                       "without sef: %s",
9860                       argno, exprNode_unparse (fcn),
9861                       exprNode_unparse (current)),
9862                      exprNode_loc (current));
9863                 }
9864             }
9865
9866           if (!sRefSet_isEmpty (sets))
9867             {
9868               sRefSet reported = sRefSet_undefined;
9869               
9870               sRefSet_realElements (current->sets, el)
9871                 {
9872                   if (sRefSet_isSameNameMember (reported, el))
9873                     {
9874                       ; /* don't report again */
9875                     }
9876                   else
9877                     {
9878                       if (sRef_isUnconstrained (el))
9879                         {
9880                           voptgenerror 
9881                             (FLG_SEFUNSPEC,
9882                              message
9883                              ("Parameter %d to %s is declared sef, but "
9884                               "the argument calls unconstrained function %s "
9885                               "(no guarantee it will not modify something): %s",
9886                               argno, exprNode_unparse (fcn),
9887                               sRef_unconstrainedName (el),
9888                               exprNode_unparse (current)),
9889                              exprNode_loc (current));
9890                         }
9891                       else
9892                         {
9893                           voptgenerror 
9894                             (FLG_SEFPARAMS,
9895                              message
9896                              ("Parameter %d to %s is declared sef, but "
9897                               "the argument may modify %q: %s",
9898                               argno, exprNode_unparse (fcn),
9899                               sRef_unparse (el),
9900                               exprNode_unparse (current)),
9901                              exprNode_loc (current));
9902                         }
9903                     } 
9904                 } end_sRefSet_realElements;
9905             }
9906         }
9907       
9908       checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9909       exprNode_mergeUSs (fcn, current);
9910     }
9911 }
9912
9913 static void
9914   checkAnyCall (/*@dependent@*/ exprNode fcn, 
9915                 /*@dependent@*/ cstring fname,
9916                 uentryList pn, 
9917                 exprNodeList args, 
9918                 bool hasMods, sRefSet mods,
9919                 bool isSpec,
9920                 int specialArgs)
9921 {
9922   int paramno = 0;
9923   int nargs = exprNodeList_size (args);
9924
9925   setCodePoint ();
9926
9927   /*
9928   ** concat all args ud's to f, add each arg sref as a use unless
9929   ** it was specified as "out", in which case it is a def.
9930   */
9931   
9932   uentryList_reset (pn);
9933   
9934   /*
9935   ** aliasing checks:
9936   **
9937   **    if paramn is only or unique, no other arg may alias argn
9938   */
9939   
9940   exprNodeList_elements (args, current) 
9941     {
9942       paramno++;
9943       
9944       if (exprNode_isDefined (current)) 
9945         {
9946           if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn))) 
9947             {
9948               uentry ucurrent = uentryList_current (pn);
9949               
9950               if (specialArgs == 0 
9951                   || (paramno < specialArgs))
9952                 {
9953                   checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
9954
9955                   if (context_maybeSet (FLG_ALIASUNIQUE))
9956                     {
9957                       if (uentry_isOnly (ucurrent)
9958                           || uentry_isUnique (ucurrent))
9959                         {
9960                           checkUniqueParams (fcn, current, args,
9961                                              paramno, ucurrent);
9962                         }
9963                     }
9964                 } 
9965             }
9966           else /* uentry is undefined */
9967             {
9968               if (specialArgs == 0)
9969                 {
9970                   exprNode_checkUseParam (current);
9971                 }
9972
9973               exprNode_mergeUSs (fcn, current);
9974             }   
9975         }
9976       uentryList_advanceSafe (pn);
9977     } end_exprNodeList_elements;
9978   
9979   if (hasMods)
9980     {
9981       setCodePoint ();
9982
9983       sRefSet_allElements (mods, s)
9984         {
9985           sRef fb;
9986           sRef rb = sRef_getRootBase (s);
9987           
9988           if (sRef_isFileOrGlobalScope (rb))
9989             {
9990               context_usedGlobal (rb);
9991             }
9992           
9993           fb = sRef_fixBaseParam (s, args);
9994           
9995           if (!sRef_isMacroParamRef (fb))
9996             {
9997               if (sRef_isNothing (fb))
9998                 {
9999                   ;
10000                 }
10001               else
10002                 {
10003                   if (sRef_isValid (fb))
10004                     {
10005                       uentry ue = sRef_getBaseUentry (s);
10006                       
10007                       if (uentry_isValid (ue))
10008                         {
10009                           uentry_setLset (ue);
10010                         }
10011                     }
10012                   
10013                   fcn->sets = sRefSet_insert (fcn->sets, fb);
10014                 }
10015             }
10016           sRef_clearDerivedComplete (s); 
10017         } end_sRefSet_allElements;
10018       
10019       setCodePoint ();
10020     }
10021   else
10022     {
10023       if (context_hasMods ())
10024         {
10025           if (context_maybeSet (FLG_MODUNCON))
10026             {
10027               voptgenerror
10028                 (FLG_MODUNCON,
10029                  message ("Undetected modification possible "
10030                           "from call to unconstrained function %s: %s", 
10031                           fname,
10032                           exprNode_unparse (fcn)),
10033                  exprNode_loc (fcn));
10034             }
10035         }
10036       else
10037         {
10038           if (context_maybeSet (FLG_MODUNCONNOMODS)
10039               && !(context_inIterDef () || context_inIterEnd ()))
10040             {
10041               voptgenerror
10042                 (FLG_MODUNCONNOMODS,
10043                  message ("Undetected modification possible "
10044                           "from call to unconstrained function %s: %s", 
10045                           fname,
10046                           exprNode_unparse (fcn)),
10047                  exprNode_loc (fcn));
10048             }
10049         }
10050
10051       exprNode_checkSetAny (fcn, fname);
10052     }
10053 }
10054
10055 void exprNode_checkUseParam (exprNode current)
10056 {
10057   if (exprNode_isDefined (current))
10058     {
10059       exprNode_checkUse (current, current->sref, current->loc);
10060     }
10061 }
10062
10063 static ctype
10064   checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10065                  /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10066                  lltok op)
10067 {
10068   ctype ret = tr1;
10069   
10070   if (!ctype_match (tr1, tr2))
10071     {
10072       if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10073           (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10074         {
10075           ;
10076         }
10077       else
10078         {
10079           (void) gentypeerror 
10080             (tr1, e1, tr2, e2,
10081              message ("Incompatible types for %s (%s, %s): %s %s %s",
10082                       lltok_unparse (op),
10083                       ctype_unparse (te1),
10084                       ctype_unparse (te2),
10085                       exprNode_unparse (e1), lltok_unparse (op), 
10086                       exprNode_unparse (e2)),
10087              e1->loc);
10088         }
10089       ret = ctype_unknown;
10090     }
10091   else
10092     {
10093       if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10094         {
10095           ret = ctype_resolveNumerics (tr1, tr2);
10096         }
10097       else if (!context_msgStrictOps ()) 
10098         {
10099                   if (ctype_isPointer (tr1))
10100             {
10101               if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10102                 {
10103                   ret = ctype_int;
10104                 }
10105               else if (ctype_isInt (tr2))
10106                 {
10107                   ret = te1;
10108                 }
10109               else
10110                 {
10111                   ret = ctype_unknown;
10112                 }
10113             }
10114           else if (ctype_isPointer (tr2))
10115             {
10116               if (ctype_isPointer (tr1))
10117                 {
10118                   ret = ctype_int;
10119                 }
10120               else if (ctype_isInt (tr1))
10121                 {
10122                   ret = te2;
10123                 }
10124               else
10125                 {
10126                   ret = ctype_unknown; 
10127                 }
10128             }
10129           else
10130             {
10131               ret = ctype_resolveNumerics (tr1, tr2);
10132             }
10133         }
10134       else
10135         {
10136           int opid = lltok_getTok (op);
10137           bool comparop = (opid == EQ_OP || opid == NE_OP 
10138                            || opid == TLT || opid == TGT
10139                            || opid == LE_OP || opid == GE_OP);
10140           
10141           if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10142             {
10143               if (comparop
10144                   && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10145                       || (ctype_isBool (tr1) && ctype_isBool (tr2))
10146                       || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10147                 {
10148                   ; /* no error */
10149                 }
10150               else
10151                 {
10152                   if (ctype_sameName (te1, te2))
10153                     {
10154                       voptgenerror
10155                         (FLG_STRICTOPS,
10156                          message ("Operands of %s are non-numeric (%t): %s %s %s",
10157                                   lltok_unparse (op), te1, 
10158                                   exprNode_unparse (e1), lltok_unparse (op), 
10159                                   exprNode_unparse (e2)),
10160                          e1->loc);
10161                     }
10162                   else
10163                     {
10164                       voptgenerror
10165                         (FLG_STRICTOPS,
10166                          message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10167                                   lltok_unparse (op), te1, te2, 
10168                                   exprNode_unparse (e1), lltok_unparse (op),
10169                                   exprNode_unparse (e2)),
10170                          e1->loc);
10171                     }
10172                 }
10173             }
10174           else if (!ctype_isNumeric (tr1))
10175             {
10176               voptgenerror
10177                 (FLG_STRICTOPS,
10178                  message ("Right operand of %s is non-numeric (%t): %s %s %s",
10179                           lltok_unparse (op), te1, 
10180                           exprNode_unparse (e1), lltok_unparse (op), 
10181                           exprNode_unparse (e2)),
10182                  e1->loc);
10183             }
10184           else 
10185             {
10186               if (!ctype_isNumeric (tr2))
10187                 {
10188                   voptgenerror
10189                     (FLG_STRICTOPS,
10190                      message ("Left operand of %s is non-numeric (%t): %s %s %s",
10191                               lltok_unparse (op), te2, 
10192                               exprNode_unparse (e1), lltok_unparse (op), 
10193                               exprNode_unparse (e2)),
10194                      e2->loc);
10195                 }
10196             }
10197           
10198           ret = ctype_unknown;
10199         }
10200     }
10201
10202   return ret;
10203 }
10204
10205 static void
10206 abstractOpError (ctype tr1, ctype tr2, lltok op, 
10207                  /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, 
10208                  fileloc loc1, fileloc loc2)
10209 {
10210   if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10211     {
10212       if (ctype_match (tr1, tr2))
10213         {
10214           voptgenerror
10215             (FLG_ABSTRACT,
10216              message ("Operands of %s are abstract type (%t): %s %s %s",
10217                       lltok_unparse (op), tr1, 
10218                       exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10219              loc1);
10220         }
10221       else
10222         {
10223           voptgenerror 
10224             (FLG_ABSTRACT,
10225              message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10226                       lltok_unparse (op), tr1, tr2, 
10227                       exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10228              loc1);
10229         }
10230     }
10231   else if (ctype_isRealAbstract (tr1))
10232     {
10233       voptgenerror
10234         (FLG_ABSTRACT,
10235          message ("Left operand of %s is abstract type (%t): %s %s %s",
10236                   lltok_unparse (op), tr1, 
10237                   exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10238          loc1);
10239     }
10240   else 
10241     {
10242       if (ctype_isRealAbstract (tr2))
10243         {
10244           voptgenerror
10245             (FLG_ABSTRACT,
10246              message ("Right operand of %s is abstract type (%t): %s %s %s",
10247                       lltok_unparse (op), tr2, 
10248                       exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10249              loc2);
10250         }
10251     }
10252 }
10253
10254 /*
10255 ** e1 <= e2
10256 **
10257 ** requies e1 and e2 and not error exprNode's.
10258 **
10259 ** Checks:
10260 **
10261 **    If e1 is a component of an abstract type, and e2 is mutable and client-visible, 
10262 **    the rep of the abstract type is exposed.
10263 **
10264 ** The order is very important:
10265 **
10266 **    check rep expose (move into check transfer)
10267 **    check transfer
10268 **    setup aliases
10269 */
10270
10271 /*
10272 ** This isn't really a sensible procedure, but the indententation
10273 ** was getting too deep.
10274 */
10275
10276 static void
10277 checkOneRepExpose (sRef ysr, sRef base, 
10278                    /*@notnull@*/ exprNode e1, 
10279                    /*@notnull@*/ exprNode e2, ctype ct,
10280                    sRef s2b)
10281 {
10282   if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr) 
10283         || sRef_isOwned (ysr) 
10284         || sRef_isExposed (ysr)))
10285     {
10286       if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10287           && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10288
10289         {
10290           if (sRef_isIReference (ysr))
10291             {
10292               if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10293                 {
10294                   voptgenerror 
10295                     (FLG_ASSIGNEXPOSE,
10296                      message
10297                      ("Assignment of mutable component of parameter %q "
10298                       "to component of abstract "
10299                       "type %s exposes rep: %s = %s",
10300                       sRef_unparse (base),
10301                       ctype_unparse (ct),
10302                       exprNode_unparse (e1), exprNode_unparse (e2)),
10303                      e1->loc);
10304                 }
10305               else
10306                 {
10307                   voptgenerror 
10308                     (FLG_ASSIGNEXPOSE,
10309                      message
10310                      ("Assignment of mutable component of parameter %q "
10311                       "(through alias %q) to component of abstract "
10312                       "type %s exposes rep: %s = %s",
10313                       sRef_unparse (base),
10314                       sRef_unparse (e2->sref),
10315                       ctype_unparse (ct),
10316                       exprNode_unparse (e1), exprNode_unparse (e2)),
10317                      e1->loc);
10318                 }
10319             }
10320           else
10321             {
10322               if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10323                 {
10324                   voptgenerror 
10325                     (FLG_ASSIGNEXPOSE,
10326                      message ("Assignment of mutable parameter %q "
10327                               "to component of abstract type %s "
10328                               "exposes rep: %s = %s",
10329                               sRef_unparse (base),
10330                               ctype_unparse (ct),
10331                               exprNode_unparse (e1), 
10332                               exprNode_unparse (e2)),
10333                      e1->loc);
10334                 }
10335               else
10336                 {
10337                   voptgenerror 
10338                     (FLG_ASSIGNEXPOSE,
10339                      message ("Assignment of mutable parameter %q "
10340                               "(through alias %q) to "
10341                               "component of abstract type %s exposes "
10342                               "rep: %s = %s",
10343                               sRef_unparse (base),
10344                               sRef_unparse (e2->sref),
10345                               ctype_unparse (ct),
10346                               exprNode_unparse (e1), 
10347                               exprNode_unparse (e2)),
10348                      e1->loc);
10349                 }
10350             }
10351         }
10352       
10353       if (sRef_isFileOrGlobalScope (s2b))
10354         {
10355           if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10356             {
10357               voptgenerror 
10358                 (FLG_REPEXPOSE,
10359                  message ("Assignment of global %q "
10360                           "to component of "
10361                           "abstract type %s exposes rep: %s = %s",
10362                           sRef_unparse (base),
10363                           ctype_unparse (ct),
10364                           exprNode_unparse (e1), exprNode_unparse (e2)),
10365                  e1->loc);
10366             }
10367           else
10368             {
10369               voptgenerror 
10370                 (FLG_REPEXPOSE,
10371                  message ("Assignment of global %q (through alias %q) "
10372                           "to component of "
10373                           "abstract type %s exposes rep: %s = %s",
10374                           sRef_unparse (base),
10375                           sRef_unparse (e2->sref),
10376                           ctype_unparse (ct),
10377                           exprNode_unparse (e1), exprNode_unparse (e2)),
10378                  e1->loc);
10379             }
10380         }
10381     }
10382 }
10383
10384 static void
10385 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10386 {
10387   if (ctype_isRealFunction (exprNode_getType (e1))
10388       && !ctype_isRealPointer (exprNode_getType (e1)))
10389     {
10390       voptgenerror 
10391         (FLG_TYPE,
10392          message ("Invalid left-hand side of assignment (function type %s): %s",
10393                   ctype_unparse (exprNode_getType (e1)),
10394                   exprNode_unparse (e1)),
10395          e1->loc);
10396     }
10397
10398   if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10399     {
10400       ctype t2 = exprNode_getType (e2);
10401       sRef sr = sRef_getRootBase (e1->sref);
10402       ctype ct = sRef_getType (sr);
10403
10404       if (ctype_isAbstract (t2) 
10405           && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10406         {
10407           /* it is immutable, okay to reference */
10408           goto donerepexpose;
10409         }
10410
10411       if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10412         {
10413           sRef s2b = sRef_getRootBase (e2->sref);
10414           sRef s1 = e1->sref;
10415           sRef s1b = sRef_getRootBase (s1);
10416           sRefSet aliases;
10417
10418           aliases = usymtab_canAlias (e2->sref);
10419           
10420           if (!sRef_similar (s2b, s1b) 
10421               && !sRef_isExposed (s1)
10422               && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10423             {
10424               if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b) 
10425                   && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10426                   && !sRef_isExposed (s2b))
10427                 {
10428                   if (sRef_isIReference (e2->sref))
10429                     {
10430                       voptgenerror 
10431                         (FLG_ASSIGNEXPOSE,
10432                          message 
10433                          ("Assignment of mutable component of parameter %q "
10434                           "to component of abstract type %s exposes rep: %s = %s",
10435                           sRef_unparse (s2b),
10436                           ctype_unparse (ct),
10437                           exprNode_unparse (e1), exprNode_unparse (e2)),
10438                          e1->loc);
10439                     }
10440                   else
10441                     {
10442                       voptgenerror 
10443                         (FLG_ASSIGNEXPOSE,
10444                          message ("Assignment of mutable parameter %q to "
10445                                   "component of abstract type %s exposes rep: %s = %s",
10446                                   sRef_unparse (s2b),
10447                                   ctype_unparse (ct),
10448                                   exprNode_unparse (e1), exprNode_unparse (e2)),
10449                          e1->loc);
10450                     }
10451                 }
10452
10453               if (sRef_isFileOrGlobalScope (s2b))
10454                 {
10455                   voptgenerror
10456                     (FLG_ASSIGNEXPOSE,
10457                      message ("Assignment of global %q to component of "
10458                               "abstract type %s exposes rep: %s = %s",
10459                               sRef_unparse (s2b),
10460                               ctype_unparse (ct),
10461                               exprNode_unparse (e1), exprNode_unparse (e2)),
10462                      e1->loc);
10463                 }
10464               
10465               sRefSet_realElements (aliases, ysr)
10466                 {
10467                   sRef base = sRef_getRootBase (ysr);
10468                   
10469                   if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10470                       || sRef_sameName (base, s1b))
10471                     {
10472                      ; /* error already reported or same sref */
10473                     }
10474                   else
10475                     {
10476                       checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10477                     }
10478                 } end_sRefSet_realElements;
10479             }
10480           sRefSet_free (aliases);
10481         }
10482     }
10483
10484  donerepexpose:
10485
10486   /*
10487   ** function variables don't really work...
10488   */
10489
10490   if (!ctype_isFunction (ctype_realType (e2->typ)))
10491     {
10492       if (isInit)
10493         {
10494             DPRINTF (("Check init: %s / %s",
10495                       exprNode_unparse (e1), exprNode_unparse (e2)));
10496           checkInitTransfer (e1, e2); 
10497         }
10498       else
10499         {
10500           checkAssignTransfer (e1, e2); 
10501         }
10502     }
10503   else
10504     {
10505       sRef fref = e2->sref;
10506
10507       sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10508       sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10509
10510             /* Need to typecheck the annotation on the parameters */
10511       
10512       if (ctype_isRealFunction (e1->typ)) {
10513         uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10514         uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10515
10516         if (!uentryList_isMissingParams (e1p)
10517             && !uentryList_isMissingParams (e2p)
10518             && uentryList_size (e1p) > 0) {
10519           if (uentryList_size (e1p) == uentryList_size (e2p)) {
10520             int n = 0;
10521             
10522             uentryList_elements (e1p, el1) {
10523               uentry el2;
10524
10525               el2 = uentryList_getN (e2p, n);
10526               n++;
10527               uentry_checkMatchParam (el1, el2, n, e2);
10528             } end_uentryList_elements;
10529           }
10530         }
10531       }
10532     }
10533
10534   if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10535     {
10536        ;
10537     }
10538   else
10539     {
10540       DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10541       updateAliases (e1, e2); 
10542     }
10543 }
10544
10545 static void 
10546 checkMacroParen (exprNode e)
10547 {
10548   if (exprNode_isError (e) || e->kind == XPR_CAST)
10549     {
10550      ;
10551     }
10552   else 
10553     {
10554       if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10555         {
10556           voptgenerror 
10557             (FLG_MACROPARENS,
10558              message ("Macro parameter used without parentheses: %s", 
10559                       exprNode_unparse (e)),
10560              e->loc);
10561         }
10562     }
10563 }
10564
10565 static void
10566 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10567 {
10568   if (isnull)
10569     {
10570       e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10571     }
10572   else
10573     {
10574       e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10575     }
10576 }
10577
10578 /*
10579 ** e1 <= e2
10580 **
10581 ** if e2 is a parameter or global derived location which
10582 ** can be modified (that is, e2 is a mutable abstract type,
10583 ** or a derived pointer), then e1 can alias e2.
10584 **
10585 ** e1 can alias everything which e2 can alias.
10586 **
10587 ** Also, if e1 is guarded, remove from guard sets!
10588 */
10589
10590 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10591 {
10592   if (!context_inProtectVars ())
10593     {
10594       /*
10595       ** depends on types of e1 and e2
10596       */
10597       
10598       sRef s1 = e1->sref;
10599       sRef s2 = e2->sref;
10600       ctype t1 = exprNode_getType (e1);
10601       
10602       /* handle pointer sRefs, record fields, arrays, etc... */
10603       
10604       if (!ctype_isRealSU (t1))
10605         {
10606           DPRINTF (("Copying real! %s", ctype_unparse (t1)));
10607           sRef_copyRealDerivedComplete (s1, s2);
10608         }
10609       else
10610         {
10611           /*
10612           ** Fields should alias
10613           */
10614
10615           DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10616         }
10617
10618       if (ctype_isMutable (t1) && sRef_isKnown (s1))
10619         {
10620           usymtab_clearAlias (s1);
10621           usymtab_addMustAlias (s1, s2); 
10622           DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10623         }
10624       else
10625         {
10626           DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
10627         }
10628
10629       if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10630         {
10631           usymtab_unguard (s1);
10632         }
10633     }
10634 }
10635
10636 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10637 {
10638   if (exprNode_isDefined (e))
10639     {
10640       e->loc = fileloc_update (e->loc, loc);
10641     }
10642   else
10643     {
10644       e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10645     }
10646
10647   return (e);
10648 }
10649
10650 static void checkUniqueParams (exprNode fcn,
10651                                /*@notnull@*/ exprNode current, 
10652                                exprNodeList args, 
10653                                int paramno, uentry ucurrent)
10654 {
10655   int iparamno = 0;
10656   sRef thisref = exprNode_getSref (current);
10657   
10658   /*
10659   ** Check if any argument could match this argument.
10660   */
10661   
10662   exprNodeList_elements (args, icurrent) 
10663     {
10664       iparamno++;
10665       
10666       if (iparamno != paramno)
10667         {
10668           sRef sr = exprNode_getSref (icurrent);
10669           
10670           if (sRef_similarRelaxed (thisref, sr))
10671             {
10672               if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10673                 {
10674                   voptgenerror 
10675                     (FLG_ALIASUNIQUE,
10676                      message
10677                      ("Parameter %d (%s) to function %s is declared %s but "
10678                       "is aliased by parameter %d (%s)",
10679                       paramno, 
10680                       exprNode_unparse (current),
10681                       exprNode_unparse (fcn),
10682                       alkind_unparse (uentry_getAliasKind (ucurrent)),
10683                       iparamno, exprNode_unparse (icurrent)),
10684                      current->loc);
10685                 }
10686             }
10687           else
10688             {
10689               sRefSet aliases = usymtab_canAlias (sr);
10690
10691               sRefSet_allElements (aliases, asr)
10692                 {
10693                   if (ctype_isUnknown (sRef_getType (thisref)))
10694                     {
10695                       sRef_setType (thisref, uentry_getType (ucurrent));
10696                     }
10697                   
10698                   if (sRef_similarRelaxed (thisref, asr)) 
10699                     {
10700                       if (sRef_isExternal (asr))  
10701                         {
10702                           if (sRef_isLocalState (thisref))
10703                             {
10704                               ; /* okay */
10705                             }
10706                           else
10707                             {
10708                               sRef base = sRef_getRootBase (asr);
10709                               
10710                               if (!sRef_similar (sRef_getBase (asr), thisref)) 
10711                                 {
10712                                   if (sRef_isUnique (base) || sRef_isOnly (base)
10713                                       || sRef_isKept (base)
10714                                       || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10715                                       || (sRef_isAddress (thisref) 
10716                                           && sRef_isLocalVar (sRef_getRootBase (thisref))))
10717                                     {
10718                                       ; /* okay, no error */
10719                                     }
10720                                   else
10721                                     {
10722                                       voptgenerror 
10723                                         (FLG_MAYALIASUNIQUE,
10724                                          message
10725                                          ("Parameter %d (%s) to function %s is declared %s but "
10726                                           "may be aliased externally by parameter %d (%s)",
10727                                           paramno, 
10728                                           exprNode_unparse (current),
10729                                           exprNode_unparse (fcn),
10730                                           alkind_unparse (uentry_getAliasKind (ucurrent)),
10731                                           iparamno, exprNode_unparse (icurrent)),
10732                                          current->loc);
10733                                     }
10734                                 }
10735                             }
10736                         }
10737                       else
10738                         {
10739                           voptgenerror 
10740                             (FLG_ALIASUNIQUE,
10741                              message
10742                              ("Parameter %d (%s) to function %s is declared %s but "
10743                               "is aliased externally by parameter %d (%s) through "
10744                               "alias %q",
10745                               paramno, 
10746                               exprNode_unparse (current),
10747                               exprNode_unparse (fcn),
10748                               alkind_unparse (uentry_getAliasKind (ucurrent)),
10749                               iparamno, exprNode_unparse (icurrent),
10750                               sRef_unparse (asr)),
10751                              current->loc);
10752                         }
10753                     }
10754                 } end_sRefSet_allElements;
10755               sRefSet_free (aliases);
10756             }
10757         }
10758     } end_exprNodeList_elements;
10759 }
10760
10761 long exprNode_getLongValue (exprNode e) {
10762   long value;
10763
10764   if (exprNode_hasValue (e) 
10765       && multiVal_isInt (exprNode_getValue (e)))
10766     {
10767       value = multiVal_forceInt (exprNode_getValue (e));
10768     }
10769   else
10770     {
10771       value = 0;
10772     }
10773   
10774   return value;
10775 }
10776
10777 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
10778 {
10779   if (exprNode_isDefined (p_e) )
10780     return ( p_e->loc );
10781   else
10782     return fileloc_undefined;
10783 }
10784
10785 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
10786 {
10787   /*
10788   ** Returns the location of the sequence point following e.
10789   **
10790   ** Only works for statements (for now).
10791   */
10792
10793   if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10794     lltok t = exprData_getUopTok (e->edata);
10795     return fileloc_copy(lltok_getLoc (t));
10796   } else {
10797     /* drl possible problem : warning fix
10798        llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
10799     */
10800     return fileloc_undefined;
10801   }
10802  }
10803
10804 exprNode exprNode_createNew(ctype c)
10805 {
10806   exprNode ret;
10807
10808   ret = exprNode_createPlain (c);
10809
10810   return ret;
10811 }
10812
10813 bool exprNode_isInitBlock (exprNode e)
10814 {
10815   return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);
10816 }
This page took 0.942006 seconds and 5 git commands to generate.