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