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