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