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