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