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