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