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