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