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