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