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