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