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