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