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