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