]> 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           exprNodeList_elements (vals, oneval)
7590             {
7591               cstring istring = message ("%d", i);
7592               exprNode newel =
7593                 exprNode_arrayFetch 
7594                   (exprNode_fakeCopy (el),
7595                    exprNode_numLiteral (ctype_int, istring,
7596                                         fileloc_copy (el->loc), i));
7597               
7598               if (exprNode_isDefined (newel))
7599                 {
7600                   if (exprNodeList_size (vals) == 1
7601                       && ctype_isString (exprNode_getType (oneval))
7602                       && ctype_isChar (exprNode_getType (newel)))
7603                     {
7604                       exprNode_freeIniter (newel);
7605                     }
7606                   else
7607                     {
7608                       if (exprNode_checkOneInit (newel, oneval))
7609                         {
7610                           hasError = TRUE;
7611                           nerrors++;
7612                           
7613                           if (nerrors > 3 && exprNodeList_size (vals) > 6)
7614                             {
7615                               llgenmsg 
7616                                 (message ("Additional initialization errors "
7617                                           "for %s not reported",
7618                                           exprNode_unparse (el)),
7619                                  exprNode_loc (el));
7620                               exprNode_freeIniter (newel);
7621                               break;
7622                             }
7623                           else
7624                             {
7625                               exprNode_freeIniter (newel);
7626                             }
7627                         }
7628                       else
7629                         {
7630                           exprNode_freeIniter (newel);
7631                         }
7632                     }
7633                 }
7634
7635               cstring_free (istring);
7636               i++;
7637               /*@-branchstate@*/ 
7638             } end_exprNodeList_elements;
7639           /*@=branchstate@*/
7640         }
7641       else if (ctype_isStruct (ctype_realType (t1)))
7642         {
7643           uentryList fields = ctype_getFields (t1);
7644           int i = 0;
7645
7646           if (uentryList_size (fields) != exprNodeList_size (vals))
7647             {
7648               if (uentryList_size (fields) > exprNodeList_size (vals))
7649                 {
7650                   hasError = optgenerror 
7651                     (FLG_FULLINITBLOCK,
7652                      message ("Initializer block for "
7653                               "%s has %d field%&, but %s has %d field%&: %q",
7654                               exprNode_unparse (el),
7655                               exprNodeList_size (vals),
7656                               ctype_unparse (t1),
7657                               uentryList_size (fields),
7658                               exprNodeList_unparse (vals)),
7659                      val->loc);   
7660                 }
7661               else
7662                 {
7663                   hasError = optgenerror 
7664                     (FLG_TYPE,
7665                      message ("Initializer block for "
7666                               "%s has %d field%&, but %s has %d field%&: %q",
7667                               exprNode_unparse (el),
7668                               exprNodeList_size (vals),
7669                               ctype_unparse (t1),
7670                               uentryList_size (fields),
7671                               exprNodeList_unparse (vals)),
7672                      val->loc);   
7673                 }
7674             }
7675           else
7676             {
7677               exprNodeList_elements (vals, oneval)
7678                 {
7679                   uentry thisfield = uentryList_getN (fields, i);
7680                   exprNode newel =
7681                     exprNode_fieldAccessAux (exprNode_fakeCopy (el),
7682                                              exprNode_loc (el),
7683                                              uentry_getName (thisfield));
7684
7685                   if (exprNode_isDefined (newel))
7686                     {
7687                       if (exprNode_checkOneInit (newel, oneval))
7688                         {
7689                           hasError = TRUE;
7690                         }
7691
7692                       exprNode_freeIniter (newel);
7693                     }
7694
7695                   i++;
7696                 } end_exprNodeList_elements;
7697             }
7698         }
7699       else
7700         {
7701           hasError = optgenerror 
7702             (FLG_TYPE,
7703              message ("Initializer block used for "
7704                       "%s where %t is expected: %s",
7705                       exprNode_unparse (el), t1, exprNode_unparse (val)),
7706              val->loc);   
7707         }
7708     }
7709   else
7710     {
7711       if (exprNode_isDefined (val))
7712         {
7713           doAssign (el, val, TRUE);
7714           
7715           if (!exprNode_matchType (t1, val))
7716             {
7717               hasError = gentypeerror 
7718                 (t1, val, t2, el,
7719                  message ("Initial value of %s is type %t, "
7720                           "expects %t: %s",
7721                           exprNode_unparse (el),
7722                           t2, t1, exprNode_unparse (val)),
7723                  val->loc);
7724             }
7725         }
7726     }
7727
7728   return hasError;
7729 }
7730
7731 static exprNode 
7732 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
7733 {
7734   exprNode ret;
7735
7736   if (usymtab_exists (idDecl_observeId (t)))
7737     {
7738       uentry ue = usymtab_lookup (idDecl_observeId (t));
7739       ret = exprNode_createId (ue);
7740
7741       /*@i723 don't do this...but why? */
7742 # if 0
7743       ct = ctype_realishType (ret->typ);
7744
7745       DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
7746
7747       if (ctype_isUnknown (ct)) 
7748         {
7749           if (uentry_isAnyTag (ue))
7750             {
7751               voptgenerror
7752                 (FLG_IMPTYPE,
7753                  message ("%s used but not previously declared: %s",
7754                           uentry_ekindName (ue),
7755                           idDecl_getName (t)),
7756                  g_currentloc);
7757               
7758             }
7759           else
7760             {
7761               voptgenerror
7762                 (FLG_IMPTYPE,
7763                  message ("Variable has unknown (implicitly int) type: %s",
7764                           idDecl_getName (t)),
7765                  g_currentloc);
7766             }
7767
7768           ct = ctype_int;
7769         }
7770 # endif
7771     }
7772   else
7773     {
7774       uentry ue = uentry_makeUnrecognized (idDecl_observeId (t),
7775                                            g_currentloc);
7776       ret = exprNode_fromIdentifierAux (ue);
7777
7778       /*
7779       ** No error - this happens in old style declarations:
7780
7781       voptgenerror
7782         (FLG_UNRECOG,
7783          message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
7784          g_currentloc);
7785
7786       ** 
7787       */
7788     }
7789
7790   exprData_free (ret->edata, ret->kind); 
7791   ret->edata = exprData_undefined;
7792   ret->exitCode = XK_NEVERESCAPE;
7793   ret->mustBreak = FALSE;
7794   ret->kind = XPR_INIT;
7795   return ret;
7796 }
7797   
7798 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
7799 {
7800   exprNode ret = exprNode_makeInitializationAux (t);
7801   llassert (ret->edata == exprData_undefined);
7802   ret->edata = exprData_makeInit (t, exprNode_undefined);
7803   return ret;
7804 }
7805
7806 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
7807                                       /*@only@*/ exprNode e)
7808 {
7809   uentry ue = usymtab_lookup (idDecl_observeId (t));
7810   exprNode ret = exprNode_makeInitializationAux (t);
7811   fileloc loc = exprNode_loc (e);
7812
7813   if (exprNode_isError (e)) 
7814     {
7815       e = exprNode_createUnknown ();
7816       idDecl_free (t);
7817
7818       /* error: assume initializer is defined */
7819       sRef_setDefined (ret->sref, g_currentloc); 
7820     }
7821   else
7822     {
7823       ctype ct = ctype_realishType (ret->typ);
7824
7825       /*
7826       ** evs - 9 Apr 1995
7827       **
7828       ** was addSafeUse --- what's the problem?
7829       **
7830       **   int x = 3, y = x ?
7831       */
7832
7833       exprData_free (ret->edata, ret->kind);
7834       ret->edata = exprData_makeInit (t, e);
7835
7836       exprNode_checkUse (ret, e->sref, e->loc);
7837       
7838       if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
7839         {
7840           exprNode lhs = exprNode_createId (ue);
7841
7842           /*
7843           ** static storage should be undefined before initializing
7844           */
7845
7846           if (uentry_isStatic (ue))
7847             {
7848               sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
7849             }
7850
7851           (void) exprNode_checkOneInit (lhs, e);
7852
7853           if (uentry_isStatic (ue))
7854             {
7855               sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
7856             }
7857
7858           exprNode_free (lhs);
7859         }
7860       else
7861         {
7862           if (!exprNode_matchType (ct, e))
7863             {
7864               if (exprNode_isZero (e) && ctype_isArrayPtr (ct)) 
7865                 {
7866                   ;
7867                 }
7868               else
7869                 {
7870                   (void) gentypeerror 
7871                     (exprNode_getType (e), e, exprNode_getType (ret), ret,
7872                      message 
7873                      ("Variable %q initialized to type %t, expects %t: %s",
7874                       uentry_getName (ue), exprNode_getType (e), 
7875                       exprNode_getType (ret),
7876                       exprNode_unparse (e)),
7877                      e->loc);
7878                 }
7879             }
7880         }
7881       
7882       if (uentry_isStatic (ue))
7883         {
7884           sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
7885         }
7886
7887       doAssign (ret, e, TRUE);
7888
7889       if (uentry_isStatic (ue))
7890         {
7891           sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
7892         }
7893     }
7894
7895   if (context_inIterDef ())
7896     {
7897       /* should check if it is yield */
7898       uentry_setUsed (ue, loc);
7899     }
7900   else
7901     {
7902       ;
7903     }
7904
7905   exprNode_mergeUSs (ret, e);
7906   return ret;
7907 }
7908   
7909 exprNode exprNode_iter (/*@observer@*/ uentry name,
7910                         /*@only@*/ exprNodeList alist, 
7911                         /*@only@*/ exprNode body,
7912                         /*@observer@*/ uentry end)
7913 {
7914   exprNode ret;
7915   cstring iname;
7916
7917   llassert (uentry_isValid (name));
7918
7919   uentry_setUsed (name, exprNode_loc (body));
7920
7921   ret = exprNode_createPartialCopy (body);
7922   iname = uentry_getName (name);
7923
7924   if (uentry_isInvalid (end))
7925     {
7926       llerror (FLG_ITER,
7927                message ("Iter %s not balanced with end_%s", iname, iname));
7928     }
7929   else
7930     {
7931       cstring ename = uentry_getName (end);
7932
7933       if (!cstring_equalPrefix (ename, "end_"))
7934         {
7935           llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s", 
7936                                       iname, iname, ename));
7937         }
7938       else
7939         {
7940           if (!cstring_equal (iname, cstring_suffix (ename, 4)))
7941             {
7942               llerror (FLG_ITER, 
7943                        message ("Iter %s not balanced with end_%s: %s", 
7944                                 iname, iname, ename));
7945             }
7946         }
7947
7948       cstring_free (ename);
7949     }
7950
7951   context_exitIterClause (body);
7952   
7953   ret->kind = XPR_ITER;
7954   ret->edata = exprData_makeIter (name, alist, body, end);
7955
7956   if (uentry_isIter (name))
7957     {
7958       (void) checkArgsReal (name, body, 
7959                             uentry_getParams (name), alist, TRUE, ret);
7960     }
7961
7962   cstring_free (iname);
7963
7964   return ret;
7965 }
7966
7967 exprNode
7968 exprNode_iterNewId (/*@only@*/ cstring s)
7969 {
7970   exprNode e = exprNode_new ();
7971   uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
7972
7973   llassert (processingIterVars ());
7974
7975   e->loc = context_getSaveLocation ();
7976
7977   if (fileloc_isUndefined (e->loc))
7978     {
7979       fileloc_free (e->loc);
7980       e->loc = fileloc_copy (g_currentloc);
7981     }
7982
7983   e->uses = sRefSet_new ();
7984   e->sets = sRefSet_new ();
7985   e->msets = sRefSet_new ();
7986   e->kind = XPR_VAR;
7987   e->val = multiVal_unknown ();
7988   e->guards = guardSet_new ();
7989   e->sref = defref;
7990   e->isJumpPoint = FALSE;
7991   e->exitCode = XK_NEVERESCAPE;
7992
7993   /*> missing fields, detected by lclint <*/
7994   e->canBreak = FALSE;
7995   e->mustBreak = FALSE;
7996   e->etext = cstring_undefined;
7997
7998   if (uentry_isYield (ue))
7999     {
8000       uentry uue = uentry_makeVariable (s, uentry_getType (ue), 
8001                                         fileloc_copy (e->loc), 
8002                                         FALSE);
8003       sRef sr;
8004
8005       uue = usymtab_supEntrySrefReturn (uue);
8006
8007       sr = uentry_getSref (uue);
8008       sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8009       sr = uentry_getSref (uue);
8010       sRef_setDefined (sr, e->loc);
8011
8012       e->typ = uentry_getType (uue);      
8013       e->sref = sr;
8014       e->edata = exprData_makeId (uue);
8015       uentry_setUsed (uue, g_currentloc);
8016     }
8017   else
8018     {
8019       uentry uue;
8020
8021       sRef_setGlobalScope ();
8022       uue = uentry_makeVariableLoc (s, ctype_unknown);
8023
8024       e->typ = ctype_unknown;
8025       e->edata = exprData_makeId (uue);
8026
8027       uentry_setUsed (uue, e->loc);
8028       uentry_setHasNameError (uue); 
8029
8030       if (context_getFlag (FLG_REPEATUNRECOG))
8031         {
8032           uentry_markOwned (uue);
8033         }
8034       else
8035         {
8036           usymtab_supGlobalEntry (uue);      
8037         }
8038
8039       sRef_clearGlobalScope ();
8040
8041       voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8042                     e->loc);
8043     }
8044
8045
8046   cstring_free (s);
8047   
8048   exprNode_defineConstraints(e);
8049   return (e);
8050 }
8051
8052 exprNode
8053 exprNode_iterExpr (/*@returned@*/ exprNode e)
8054 {
8055   if (!processingIterVars ())
8056     {
8057       llcontbuglit ("checkIterParam: not in iter");
8058       return e;
8059     }
8060   
8061   if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()), 
8062                                        iterParamNo ())))
8063     {
8064       if (exprNode_isDefined (e))
8065         {
8066           if (fileloc_isDefined (e->loc))
8067             {
8068               voptgenerror
8069                 (FLG_ITER,
8070                  message ("Yield parameter is not simple identifier: %s", 
8071                           exprNode_unparse (e)),
8072                  e->loc);
8073             }
8074           else
8075             {
8076               voptgenerror
8077                 (FLG_ITER,
8078                  message ("Yield parameter is not simple identifier: %s",
8079                           exprNode_unparse (e)),
8080                  g_currentloc);
8081               
8082             }
8083         }
8084     }
8085   return e;
8086 }
8087
8088 exprNode
8089 exprNode_iterId (/*@observer@*/ uentry c)
8090 {
8091   uentry ue;
8092
8093   llassert (processingIterVars ());
8094
8095   ue = uentryList_getN (uentry_getParams (getCurrentIter ()), 
8096                         iterParamNo ());
8097
8098   if (uentry_isYield (ue))
8099     {
8100       ctype ct = uentry_getType (ue);
8101       exprNode e = exprNode_createPlain (ct);
8102       cstring name = uentry_getName (c);
8103       uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8104
8105       uentry_setUsed (ue, g_currentloc);
8106       uentry_setHasNameError (ue); 
8107       
8108       cstring_free (name);
8109       
8110       e->kind = XPR_VAR;
8111       e->edata = exprData_makeId (le);
8112       e->loc = context_getSaveLocation ();
8113       e->sref = uentry_getSref (le);
8114
8115       usymtab_supEntrySref (le);
8116
8117       if (!context_inHeader ())
8118         {
8119           if (optgenerror
8120               (FLG_ITER,
8121                message ("Yield parameter shadows local declaration: %q",
8122                         uentry_getName (c)),
8123                fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8124             {
8125               uentry_showWhereDeclared (c);
8126             }
8127         }
8128
8129       return e;
8130     }
8131
8132   return (exprNode_fromIdentifierAux (c));
8133 }
8134
8135 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8136 {
8137   exprNode ret = exprNode_create (ctype_unknown);
8138
8139   ret->kind = XPR_ITERCALL;
8140   ret->edata = exprData_makeIterCall (name, alist);
8141   
8142   if (uentry_isIter (name))
8143     {
8144       uentryList params = uentry_getParams (name);
8145
8146       if (context_inIterDef () 
8147           && uentryList_size (params) == exprNodeList_size (alist))
8148         {
8149           int i = 0;
8150           
8151           exprNodeList_elements (alist, arg)
8152             {
8153               uentry parg = uentryList_getN (params, i);
8154
8155               if (uentry_isYield (parg))
8156                 {
8157                   uentry ue = exprNode_getUentry (arg);
8158
8159                   if (uentry_isValid (ue))
8160                     {
8161                       ;
8162                     }
8163                 }
8164
8165               i++;
8166             } end_exprNodeList_elements;
8167         }
8168
8169       (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8170       checkUnspecCall (ret, params, alist);
8171     }
8172
8173   return ret;
8174 }
8175
8176 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8177 {
8178   if (exprNode_isDefined (e))
8179     {
8180       /*@access sRef@*/
8181       if (e->sref == defref) /*@noaccess sRef@*/
8182         {
8183           /*@-mods@*/
8184           e->sref = sRef_makeUnknown (); 
8185           sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8186           /*@=mods@*/
8187           return e->sref;
8188         }
8189       else
8190         {
8191           return e->sref;
8192         }
8193     }
8194   else
8195     {
8196       return sRef_undefined;
8197     }
8198 }
8199
8200 /*@observer@*/ cstring
8201 exprNode_unparseFirst (exprNode e)
8202 {
8203   if (exprNode_isDefined (e))
8204     {
8205       cstring ret;
8206
8207       if (e->kind == XPR_STMTLIST
8208           || e->kind == XPR_COMMA || e->kind == XPR_COND)
8209         {
8210           exprNode first = exprData_getPairA (e->edata);
8211
8212           if (exprNode_isDefined (first))
8213             {
8214               return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8215             }
8216           else
8217             {
8218               return (cstring_makeLiteralTemp ("..."));
8219             }
8220         }
8221
8222       ret = cstring_elide (exprNode_unparse (e), 20);
8223       cstring_markOwned (ret);
8224       
8225       return (ret);
8226     }
8227   else
8228     {
8229       return cstring_makeLiteralTemp ("<error>");
8230     }
8231 }
8232
8233 /*@observer@*/ cstring
8234 exprNode_unparse (/*@temp@*/ exprNode e)
8235 {
8236   if (exprNode_isError (e))
8237     {
8238       return cstring_makeLiteralTemp ("<error>");
8239     }
8240
8241   if (cstring_isDefined (e->etext))
8242     {
8243       return e->etext;
8244     }
8245   else
8246     {
8247       cstring ret = exprNode_doUnparse (e);
8248
8249       /*@-modifies@*/ /* benevolent */
8250       e->etext = ret; 
8251       /*@=modifies@*/
8252       return ret;
8253     }
8254 }
8255
8256 /*@observer@*/ fileloc
8257 exprNode_loc (exprNode e)
8258 {
8259   if (exprNode_isError (e))
8260     {
8261       return (g_currentloc);
8262     }
8263   else
8264     {
8265       return (e->loc);
8266     }
8267 }
8268
8269 /*
8270 ** executes exprNode e
8271 **    recursively rexecutes as though in original parse using
8272 **    information in e->edata
8273 */
8274
8275 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8276 {
8277   exprNodeList ret = exprNodeList_new ();
8278
8279   exprNodeList_elements (e, current)
8280     {
8281       exprNodeList_addh (ret, exprNode_effect (current));
8282     } end_exprNodeList_elements;
8283
8284   return ret;
8285 }
8286
8287 static /*@only@*/ exprNode exprNode_effect (exprNode e) 
8288    /*@globals internalState@*/
8289 {
8290   bool innerEffect = inEffect;
8291   exprNode ret;
8292   exprData data;
8293
8294   inEffect = TRUE;
8295
8296   context_clearJustPopped ();
8297
8298   if (exprNode_isError (e))
8299     {
8300       ret = exprNode_undefined;
8301     }
8302   else
8303     {
8304       /*
8305       ** Turn off expose and dependent transfer checking.
8306       ** Need to pass exposed internal nodes,
8307       ** [ copying would be a waste! ]
8308       ** [ Actually, I think I wasted a lot more time than its worth ]
8309       ** [ trying to do this. ]
8310       */
8311
8312       /*@-exposetrans@*/
8313       /*@-observertrans@*/
8314       /*@-dependenttrans@*/
8315       
8316       data = e->edata;
8317       
8318       switch (e->kind)
8319         {
8320         case XPR_PARENS: 
8321           ret = exprNode_addParens (exprData_getUopTok (data), 
8322                                     exprNode_effect (exprData_getUopNode (data)));
8323           break;
8324         case XPR_ASSIGN:
8325           ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)), 
8326                                  exprNode_effect (exprData_getOpB (data)), 
8327                                  exprData_getOpTok (data));
8328           break;
8329         case XPR_INITBLOCK:
8330           ret = exprNode_undefined;
8331           break;
8332         case XPR_CALL:
8333           ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8334                                        exprNodeList_effect (exprData_getArgs (data)));
8335           break;
8336         case XPR_EMPTY:
8337           ret = e;
8338           break;
8339
8340         case XPR_LABEL:
8341           ret = e;
8342           break;
8343
8344         case XPR_CONST:
8345         case XPR_VAR:
8346           {
8347             cstring id = exprData_getId (data);
8348             uentry ue = usymtab_lookupSafe (id);
8349
8350             ret = exprNode_fromIdentifierAux (ue);
8351             ret->loc = fileloc_update (ret->loc, e->loc);
8352             break;
8353           }
8354         case XPR_BODY:
8355           ret = e;
8356           break;
8357         case XPR_FETCH:
8358           ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)), 
8359                                      exprNode_effect (exprData_getPairB (data)));
8360           break;
8361         case XPR_OP:
8362           ret = exprNode_op (exprNode_effect (exprData_getOpA (data)), 
8363                              exprNode_effect (exprData_getOpB (data)), 
8364                              exprData_getOpTok (data));
8365           break;
8366           
8367         case XPR_POSTOP:
8368           ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)), 
8369                                  exprData_getUopTok (data));
8370           break;
8371         case XPR_PREOP:
8372           ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)), 
8373                                 exprData_getUopTok (data));
8374           break;
8375
8376         case XPR_OFFSETOF:
8377         case XPR_SIZEOFT:
8378         case XPR_SIZEOF:
8379         case XPR_ALIGNOFT:
8380         case XPR_ALIGNOF:
8381           ret = e;
8382           break;
8383           
8384         case XPR_VAARG:
8385           ret = exprNode_vaArg (exprData_getCastTok (data),
8386                                 exprNode_effect (exprData_getCastNode (data)),
8387                                 exprData_getCastType (data));
8388           break;
8389           
8390         case XPR_CAST:
8391           ret = exprNode_cast (exprData_getCastTok (data), 
8392                                exprNode_effect (exprData_getCastNode (data)), 
8393                                exprData_getCastType (data));
8394           break;
8395         case XPR_ITERCALL:
8396           ret = exprNode_iterStart (exprData_getIterCallIter (data),
8397                                     exprNodeList_effect 
8398                                     (exprData_getIterCallArgs (data)));
8399           break;
8400           
8401         case XPR_ITER:
8402           ret = exprNode_iter (exprData_getIterSname (data),
8403                                exprNodeList_effect (exprData_getIterAlist (data)),
8404                                exprNode_effect (exprData_getIterBody (data)),
8405                                exprData_getIterEname (data));
8406           break;
8407           
8408         case XPR_FOR:
8409           ret = exprNode_for (exprNode_effect (exprData_getPairA (data)), 
8410                               exprNode_effect (exprData_getPairB (data)));
8411           break;
8412           
8413         case XPR_FORPRED:
8414           ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8415                                   exprNode_effect (exprData_getTripleTest (data)),
8416                                   exprNode_effect (exprData_getTripleInc (data)));
8417           break;
8418           
8419         case XPR_TOK:
8420           ret = exprNode_createTok (exprData_getTok (data));
8421           break;
8422           
8423         case XPR_GOTO:
8424           ret = exprNode_goto (exprData_getLiteral (data));
8425           ret->loc = fileloc_update (ret->loc, e->loc);
8426           break;
8427           
8428         case XPR_CONTINUE:
8429           ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8430           break;
8431           
8432         case XPR_BREAK:
8433           ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8434           break;
8435           
8436         case XPR_RETURN:
8437           ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8438           break;
8439           
8440         case XPR_NULLRETURN:
8441           ret = exprNode_nullReturn (exprData_getTok (data));
8442           break;
8443           
8444         case XPR_COMMA:
8445           ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8446                                 exprNode_effect (exprData_getPairB (data)));
8447           break;
8448           
8449         case XPR_COND:
8450           ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8451                                exprNode_effect (exprData_getTripleTrue (data)),
8452                                exprNode_effect (exprData_getTripleFalse (data)));
8453           break;
8454         case XPR_IF:
8455           ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8456                              exprNode_effect (exprData_getPairB (data)));
8457           break;
8458           
8459         case XPR_IFELSE:
8460           ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8461                                  exprNode_effect (exprData_getTripleTrue (data)),
8462                                  exprNode_effect (exprData_getTripleFalse (data)));
8463           break;
8464         case XPR_WHILEPRED:
8465           ret = exprNode_whilePred (exprData_getSingle (data));
8466           break;
8467           
8468         case XPR_WHILE:
8469           ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8470                                 exprNode_effect (exprData_getPairB (data)));
8471           break;
8472           
8473         case XPR_DOWHILE:
8474           ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8475                                   exprNode_effect (exprData_getPairB (data)));
8476           break;
8477
8478         case XPR_BLOCK:
8479           ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8480           break;          
8481
8482         case XPR_STMT:
8483           ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8484                                     exprData_getUopTok (data));
8485           break;
8486           
8487         case XPR_STMTLIST:
8488           ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8489                                  exprNode_effect (exprData_getPairB (data)));
8490           break;
8491           
8492         case XPR_FTCASE:
8493         case XPR_CASE:
8494           ret = exprNode_caseMarker 
8495             (exprNode_effect (exprData_getSingle (data)),
8496              TRUE);
8497           break;
8498           
8499         case XPR_FTDEFAULT:
8500         case XPR_DEFAULT:
8501           ret = exprNode_createTok (exprData_getTok (data));
8502           break;
8503           
8504         case XPR_SWITCH:
8505           ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8506                                  exprNode_effect (exprData_getPairB (data)));
8507           break;
8508           
8509         case XPR_INIT:
8510           ret = exprNode_makeInitialization
8511             (exprData_getInitId (data),
8512              exprNode_effect (exprData_getInitNode (data)));
8513           break;
8514           
8515         case XPR_FACCESS:
8516           ret = exprNode_fieldAccessAux
8517             (exprNode_effect (exprData_getFieldNode (data)),
8518              exprNode_loc (exprData_getFieldNode (data)),
8519              cstring_copy (exprData_getFieldName (data)));
8520           break;
8521           
8522         case XPR_ARROW:
8523           ret = exprNode_arrowAccessAux
8524             (exprNode_effect (exprData_getFieldNode (data)),
8525              exprNode_loc (exprData_getFieldNode (data)),
8526              cstring_copy (exprData_getFieldName (data)));
8527           break;
8528           
8529         case XPR_STRINGLITERAL:
8530           ret = e;
8531           break;
8532           
8533         case XPR_NUMLIT:
8534           ret = e;
8535           break;
8536
8537         case XPR_NODE:
8538           ret = e;
8539           break;
8540           /*@-branchstate@*/ 
8541         } 
8542       /*@=branchstate@*/
8543       /*@=observertrans@*/
8544       /*@=exposetrans@*/
8545       /*@=dependenttrans@*/
8546     }
8547
8548   if (!innerEffect) 
8549     {
8550       inEffect = FALSE;
8551     }
8552
8553   return ret;
8554 }
8555
8556 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8557 {
8558   cstring ret;
8559   exprData data;
8560
8561   if (exprNode_isError (e))
8562     {
8563       return cstring_undefined;
8564     }
8565
8566   data = e->edata;
8567
8568   switch (e->kind)
8569     {
8570     case XPR_PARENS: 
8571       ret = exprNode_rootVarName (exprData_getUopNode (data));
8572       break;
8573     case XPR_ASSIGN:
8574       ret = exprNode_rootVarName (exprData_getOpA (data));
8575       break;
8576     case XPR_CONST:
8577     case XPR_VAR:
8578       ret = exprData_getId (data);
8579       break;
8580     case XPR_LABEL:
8581     case XPR_TOK:
8582     case XPR_ITERCALL:
8583     case XPR_EMPTY:
8584     case XPR_CALL:
8585     case XPR_INITBLOCK:
8586     case XPR_BODY:
8587     case XPR_FETCH:
8588     case XPR_OP:
8589     case XPR_POSTOP:
8590     case XPR_PREOP:
8591     case XPR_OFFSETOF:
8592     case XPR_ALIGNOFT:
8593     case XPR_ALIGNOF:
8594     case XPR_SIZEOFT:
8595     case XPR_SIZEOF:
8596     case XPR_VAARG:
8597     case XPR_CAST:
8598     case XPR_ITER:
8599     case XPR_FOR:
8600     case XPR_FORPRED:
8601     case XPR_BREAK:
8602     case XPR_RETURN:
8603     case XPR_NULLRETURN:
8604     case XPR_COMMA:
8605     case XPR_COND:
8606     case XPR_IF:
8607     case XPR_IFELSE:
8608     case XPR_WHILE:
8609     case XPR_WHILEPRED:
8610     case XPR_DOWHILE:
8611     case XPR_GOTO:
8612     case XPR_CONTINUE:
8613     case XPR_FTDEFAULT:
8614     case XPR_DEFAULT:
8615     case XPR_SWITCH:
8616     case XPR_FTCASE:
8617     case XPR_CASE:
8618     case XPR_BLOCK:
8619     case XPR_STMT:
8620     case XPR_STMTLIST:
8621     case XPR_INIT:
8622     case XPR_FACCESS:
8623     case XPR_ARROW:
8624     case XPR_NODE:
8625     case XPR_NUMLIT:
8626     case XPR_STRINGLITERAL:
8627       ret = cstring_undefined;
8628       break;
8629     }
8630
8631   return ret;
8632 }
8633
8634 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8635 {
8636   cstring ret;
8637   exprData data;
8638
8639   if (exprNode_isError (e))
8640     {
8641       static /*@only@*/ cstring error = cstring_undefined;
8642
8643       if (!cstring_isDefined (error))
8644         {
8645           error = cstring_makeLiteral ("<error>");
8646         }
8647       
8648       return error;
8649     }
8650
8651   data = e->edata;
8652
8653   switch (e->kind)
8654     {
8655     case XPR_PARENS: 
8656       ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8657       break;
8658     case XPR_ASSIGN:
8659       ret = message ("%s %s %s",
8660                      exprNode_unparse (exprData_getOpA (data)), 
8661                      lltok_unparse (exprData_getOpTok (data)),
8662                      exprNode_unparse (exprData_getOpB (data)));
8663       break;
8664     case XPR_CALL:
8665       ret = message ("%s(%q)",
8666                      exprNode_unparse (exprData_getFcn (data)), 
8667                      exprNodeList_unparse (exprData_getArgs (data)));
8668       break;
8669     case XPR_INITBLOCK:
8670       ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8671       break;
8672     case XPR_EMPTY:
8673       ret = cstring_undefined;
8674       break;
8675     case XPR_LABEL:
8676       ret = message ("%s:", exprData_getId (data));
8677       break;
8678     case XPR_CONST:
8679     case XPR_VAR:
8680       ret = cstring_copy (exprData_getId (data));
8681       break;
8682     case XPR_FETCH:
8683       ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8684                      exprNode_unparse (exprData_getPairB (data)));
8685       break;
8686     case XPR_BODY:
8687       ret = message ("<body>");
8688       break;
8689     case XPR_OP:
8690       ret = message ("%s %s %s",
8691                      exprNode_unparse (exprData_getOpA (data)), 
8692                      lltok_unparse (exprData_getOpTok (data)),
8693                      exprNode_unparse (exprData_getOpB (data))); 
8694       break;
8695       
8696     case XPR_PREOP: 
8697       ret = message ("%s%s",
8698                      lltok_unparse (exprData_getUopTok (data)),
8699                      exprNode_unparse (exprData_getUopNode (data))); 
8700       break;
8701
8702     case XPR_POSTOP:
8703       ret = message ("%s%s",
8704                      exprNode_unparse (exprData_getUopNode (data)),
8705                      lltok_unparse (exprData_getUopTok (data))); 
8706       break;
8707       
8708     case XPR_OFFSETOF:
8709       ret = message ("offsetof(%s,%q)", 
8710                      ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8711                      cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8712       break;
8713
8714     case XPR_SIZEOFT:
8715       ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8716       break;
8717       
8718     case XPR_SIZEOF:
8719       ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8720       break;
8721
8722     case XPR_ALIGNOFT:
8723       ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8724       break;
8725       
8726     case XPR_ALIGNOF:
8727       ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8728       break;
8729       
8730     case XPR_VAARG:
8731       ret = message ("va_arg(%s, %q)", 
8732                      exprNode_unparse (exprData_getCastNode (data)),
8733                      qtype_unparse (exprData_getCastType (data)));
8734       break;
8735       
8736     case XPR_ITERCALL:
8737       ret = message ("%q(%q)", 
8738                      uentry_getName (exprData_getIterCallIter (data)),
8739                      exprNodeList_unparse (exprData_getIterCallArgs (data)));
8740       break;
8741     case XPR_ITER:
8742       ret = message ("%q(%q) %s %q",
8743                      uentry_getName (exprData_getIterSname (data)),
8744                      exprNodeList_unparse (exprData_getIterAlist (data)),
8745                      exprNode_unparse (exprData_getIterBody (data)),
8746                      uentry_getName (exprData_getIterEname (data)));
8747       break;
8748     case XPR_CAST:
8749       ret = message ("(%q)%s", 
8750                      qtype_unparse (exprData_getCastType (data)),
8751                      exprNode_unparse (exprData_getCastNode (data)));
8752       break;
8753       
8754     case XPR_FOR:
8755       ret = message ("%s %s", 
8756                      exprNode_unparse (exprData_getPairA (data)), 
8757                      exprNode_unparse (exprData_getPairB (data)));
8758       break;
8759
8760     case XPR_FORPRED:
8761             ret = message ("for (%s; %s; %s)",
8762                      exprNode_unparse (exprData_getTripleInit (data)),
8763                      exprNode_unparse (exprData_getTripleTest (data)),
8764                      exprNode_unparse (exprData_getTripleInc (data)));
8765       break;
8766       
8767     case XPR_GOTO:
8768       ret = message ("goto %s", exprData_getLiteral (data));
8769       break;
8770
8771     case XPR_CONTINUE:
8772       ret = cstring_makeLiteral ("continue");
8773       break;
8774
8775     case XPR_BREAK:
8776       ret = cstring_makeLiteral ("break");
8777       break;
8778
8779     case XPR_RETURN:
8780       ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
8781       break;
8782
8783     case XPR_NULLRETURN:
8784       ret = cstring_makeLiteral ("return");
8785       break;
8786
8787     case XPR_COMMA:
8788       ret = message ("%s, %s", 
8789                      exprNode_unparse (exprData_getPairA (data)),
8790                      exprNode_unparse (exprData_getPairB (data)));
8791       break;
8792       
8793     case XPR_COND:
8794       ret = message ("%s ? %s : %s",
8795                      exprNode_unparse (exprData_getTriplePred (data)),
8796                      exprNode_unparse (exprData_getTripleTrue (data)),
8797                      exprNode_unparse (exprData_getTripleFalse (data)));
8798       break;
8799     case XPR_IF:
8800       ret = message ("if (%s) %s", 
8801                      exprNode_unparse (exprData_getPairA (data)),
8802                      exprNode_unparse (exprData_getPairB (data)));
8803       break;
8804       
8805     case XPR_IFELSE:
8806       ret = message ("if (%s) %s else %s",
8807                      exprNode_unparse (exprData_getTriplePred (data)),
8808                      exprNode_unparse (exprData_getTripleTrue (data)),
8809                      exprNode_unparse (exprData_getTripleFalse (data)));
8810       break;
8811     case XPR_WHILE:
8812       ret = message ("while (%s) %s",
8813                      exprNode_unparse (exprData_getPairA (data)),
8814                      exprNode_unparse (exprData_getPairB (data)));
8815       break;
8816
8817     case XPR_WHILEPRED:
8818       ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
8819       break;
8820
8821     case XPR_TOK:
8822       ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
8823       break;
8824
8825     case XPR_DOWHILE:
8826       ret = message ("do { %s } while (%s)",
8827                      exprNode_unparse (exprData_getPairB (data)),
8828                      exprNode_unparse (exprData_getPairA (data)));
8829       break;
8830       
8831     case XPR_BLOCK:
8832       ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
8833       break;
8834
8835     case XPR_STMT:
8836       ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
8837       break;
8838
8839     case XPR_STMTLIST:
8840       ret = message ("%s; %s", 
8841                      exprNode_unparse (exprData_getPairA (data)),
8842                      exprNode_unparse (exprData_getPairB (data)));
8843       break;
8844       
8845     case XPR_FTDEFAULT:
8846     case XPR_DEFAULT:
8847       ret = cstring_makeLiteral ("default:");
8848       break;
8849
8850     case XPR_SWITCH:
8851       ret = message ("switch (%s) %s", 
8852                      exprNode_unparse (exprData_getPairA (data)),
8853                      exprNode_unparse (exprData_getPairB (data)));
8854       break;
8855
8856     case XPR_FTCASE:
8857     case XPR_CASE:
8858       ret = message ("case %s:", 
8859                      exprNode_unparse (exprData_getSingle (data)));
8860       break;
8861       
8862     case XPR_INIT:
8863       if (exprNode_isError (exprData_getInitNode (data)))
8864         {
8865           ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
8866         }
8867       else
8868         {
8869           ret = message ("%q = %s",
8870                          idDecl_unparseC (exprData_getInitId (data)),
8871                          exprNode_unparse (exprData_getInitNode (data)));
8872         }
8873       break;
8874       
8875     case XPR_FACCESS:
8876       ret = message ("%s.%s",
8877                      exprNode_unparse (exprData_getFieldNode (data)),
8878                      exprData_getFieldName (data));
8879       break;
8880       
8881     case XPR_ARROW:
8882             ret = message ("%s->%s",
8883                      exprNode_unparse (exprData_getFieldNode (data)),
8884                      exprData_getFieldName (data));
8885       break;
8886
8887     case XPR_STRINGLITERAL:
8888       ret = message ("\"%s\"", exprData_getLiteral (data));
8889       break;
8890
8891     case XPR_NUMLIT:
8892       ret = cstring_copy (exprData_getLiteral (data));
8893       break;
8894
8895     case XPR_NODE:
8896       ret = cstring_makeLiteral ("<node>");
8897       break;
8898     }
8899
8900   return ret;
8901 }
8902
8903 bool
8904 exprNode_isInitializer (exprNode e)
8905 {
8906   return (exprNode_isDefined (e)
8907           && e->kind == XPR_INIT);
8908 }
8909
8910 bool 
8911 exprNode_isCharLit (exprNode e)
8912 {
8913   if (exprNode_isDefined (e))
8914     {
8915       return (multiVal_isChar (exprNode_getValue (e)));
8916     }
8917   else
8918     {
8919       return FALSE;
8920     }
8921 }
8922
8923 bool
8924 exprNode_isNumLit (exprNode e)
8925 {
8926   if (exprNode_isDefined (e))
8927     {
8928       return (multiVal_isInt (exprNode_getValue (e)));
8929     }
8930   else
8931     {
8932       return FALSE;
8933     }
8934 }
8935
8936 static bool
8937 exprNode_isFalseConstant (exprNode e)
8938 {
8939   if (exprNode_isDefined (e))
8940     {
8941       cstring s = exprNode_rootVarName (e);
8942
8943       if (cstring_equal (s, context_getFalseName ()))
8944         {
8945           return TRUE;
8946         }
8947     }
8948
8949   return FALSE;
8950 }
8951
8952 bool
8953 exprNode_matchLiteral (ctype expected, exprNode e)
8954 {
8955   if (exprNode_isDefined (e))
8956     {
8957       multiVal m = exprNode_getValue (e);
8958       
8959       if (multiVal_isDefined (m))
8960         {
8961           if (multiVal_isInt (m))
8962             {
8963               long int val = multiVal_forceInt (m);
8964               
8965               if (ctype_isDirectBool (ctype_realishType (expected)))
8966                 {
8967                   if (val == 0) 
8968                     {
8969                       return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
8970                     }
8971                   else 
8972                     {
8973                       return FALSE;
8974                     }
8975                 }
8976               
8977               if (ctype_isRealInt (expected))
8978                 {
8979                   /*
8980                   ** unsigned <- [ constant >= 0 is okay ]
8981                   */
8982                   
8983                   if (ctype_isUnsigned (expected))
8984                     {
8985                       if (val < 0)
8986                         {
8987                           return FALSE;
8988                         }
8989                     }
8990                   
8991                   /*
8992                   ** No checks on sizes of integers...maybe add
8993                   ** these later.
8994                   */
8995
8996                   DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
8997                   DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
8998                             bool_unparse (ctype_isInt (exprNode_getType (e)))));
8999
9000                   if (context_getFlag (FLG_NUMLITERAL) 
9001                       && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9002                     return TRUE;
9003                   } else {
9004                     if (val == 0) {
9005                       return TRUE;
9006                     } else {
9007                       return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9008                     }
9009                   }
9010                 }
9011               else if (ctype_isChar (expected))
9012                 {
9013                   return FALSE;
9014                 }
9015               else if (ctype_isArrayPtr (expected))
9016                 {
9017                   return (val == 0);
9018                 }
9019               else if (ctype_isAnyFloat (expected))
9020                 {
9021                   return (context_getFlag (FLG_NUMLITERAL));
9022                 }
9023               else
9024                 {
9025                   return FALSE;
9026                 }
9027             }
9028           else if (multiVal_isDouble (m))
9029             {
9030               if (ctype_isAnyFloat (expected))
9031                 {
9032                   return TRUE;
9033                 }
9034             }
9035           else if (multiVal_isChar (m))
9036             {
9037               char val = multiVal_forceChar (m);          
9038               
9039               if (ctype_isChar (expected))
9040                 {
9041                   if (ctype_isUnsigned (expected) && ((int)val) < 0)
9042                     {
9043                       return FALSE;
9044                     }
9045                   else
9046                     {
9047                       return TRUE;
9048                     }
9049                 }
9050             }
9051           else
9052             {
9053               return FALSE;
9054             }
9055         }
9056     }
9057   
9058   return FALSE;
9059 }
9060
9061 bool
9062 exprNode_matchType (ctype expected, exprNode e)
9063 {
9064   ctype actual;
9065   
9066   if (!exprNode_isDefined (e)) return TRUE;
9067
9068   actual = ctype_realishType (exprNode_getType (e));
9069
9070   if (ctype_match (ctype_realishType (expected), actual))
9071     {
9072       return TRUE;
9073     }
9074
9075   llassert (!exprNode_isError (e));
9076   return (exprNode_matchLiteral (expected, e));
9077 }
9078
9079 static bool
9080 exprNode_matchTypes (exprNode e1, exprNode e2)
9081 {
9082   ctype t1;
9083   ctype t2;
9084  
9085   if (!exprNode_isDefined (e1)) return TRUE;
9086   if (!exprNode_isDefined (e2)) return TRUE;
9087
9088   /*
9089   ** realish type --- keep bools, bools 
9090   */ 
9091
9092   t1 = ctype_realishType (exprNode_getType (e1));
9093   t2 = ctype_realishType (exprNode_getType (e2));
9094
9095   if (ctype_match (t1, t2)) 
9096     {
9097       return TRUE;
9098     }
9099
9100   return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9101 }
9102
9103 /*
9104 ** pass e as ct
9105 */
9106
9107 static bool
9108   exprNode_matchArgType (ctype ct, exprNode e)
9109 {
9110   ctype et;
9111
9112   if (!exprNode_isDefined (e))
9113     {
9114       return TRUE;
9115     }
9116
9117   et = ctype_realType (exprNode_getType (e));
9118
9119   if (ctype_matchArg (ct, et)) return TRUE;
9120   
9121   llassert (!exprNode_isError (e));
9122   return (exprNode_matchLiteral (ct, e));
9123 }
9124
9125 static /*@only@*/ exprNodeSList
9126   exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9127 {
9128   if (exprNode_isDefined (e))
9129     {
9130       if (e->kind == XPR_STMTLIST)
9131         {
9132           return (exprNodeSList_append
9133                   (exprNode_flatten (exprData_getPairA (e->edata)),
9134                    exprNode_flatten (exprData_getPairB (e->edata))));
9135         }
9136       else if (e->kind == XPR_BLOCK)
9137         {
9138           return (exprNode_flatten (exprData_getSingle (e->edata)));
9139         }
9140       else
9141         {
9142           return (exprNodeSList_singleton (e));
9143         }
9144     }
9145
9146   return exprNodeSList_new ();
9147 }
9148
9149 static /*@exposed@*/ exprNode
9150 exprNode_lastStatement (/*@returned@*/ exprNode e)
9151 {
9152   if (exprNode_isDefined (e))
9153     {
9154       if (e->kind == XPR_STMTLIST)
9155         {
9156           exprNode b = exprData_getPairB (e->edata);
9157
9158           if (exprNode_isDefined (b))
9159             {
9160               return exprNode_lastStatement (b);
9161             }
9162           else
9163             {
9164               return exprNode_lastStatement (exprData_getPairA (e->edata));
9165             }
9166         }
9167       else if (e->kind == XPR_BLOCK)
9168         {
9169           return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9170         }
9171       else
9172         {
9173           return (e);
9174         }
9175     }
9176
9177   return exprNode_undefined;
9178 }
9179
9180 static /*@exposed@*/ exprNode
9181 exprNode_firstStatement (/*@returned@*/ exprNode e)
9182 {
9183   if (exprNode_isDefined (e))
9184     {
9185       if (e->kind == XPR_STMTLIST)
9186         {
9187           exprNode b = exprData_getPairA (e->edata);
9188
9189           if (exprNode_isDefined (b))
9190             {
9191               return exprNode_firstStatement (b);
9192             }
9193           else
9194             {
9195               return exprNode_firstStatement (exprData_getPairB (e->edata));
9196             }
9197         }
9198       else if (e->kind == XPR_BLOCK)
9199         {
9200           return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9201         }
9202       else
9203         {
9204           return (e);
9205         }
9206     }
9207
9208   return exprNode_undefined;
9209 }
9210   
9211 static void
9212 exprNode_mergeUSs (exprNode res, exprNode other)
9213 {
9214   if (exprNode_isDefined (res) && exprNode_isDefined (other))
9215     {
9216       res->msets = sRefSet_union (res->msets, other->msets);
9217       res->sets = sRefSet_union (res->sets, other->sets);
9218       res->uses = sRefSet_union (res->uses, other->uses);
9219     }
9220 }
9221
9222 static void
9223 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9224 {
9225   if (exprNode_isDefined (res))
9226     {
9227       if (exprNode_isDefined (other1))
9228         {
9229           res->sets = sRefSet_union (res->sets, other1->sets);
9230           res->msets = sRefSet_union (res->msets, other1->msets);
9231           res->uses = sRefSet_union (res->uses, other1->uses);
9232         }
9233       if (exprNode_isDefined (other2))
9234         {
9235           res->sets = sRefSet_union (res->sets, other2->sets);
9236           res->msets = sRefSet_union (res->msets, other2->msets);
9237           res->uses = sRefSet_union (res->uses, other2->uses);
9238         }
9239     }
9240 }
9241
9242 /*
9243 ** modifies e->uses
9244 **
9245 ** Reports errors is s is not defined.
9246 */
9247
9248 static void
9249 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9250 {
9251   if (exprNode_isDefined (e))
9252     {
9253       e->uses = sRefSet_insert (e->uses, s);
9254     }
9255 }
9256   
9257 void
9258 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9259 {
9260   if (sRef_isKnown (s) && !sRef_isConst (s))
9261     {
9262       /*
9263       ** need to check all outer types are useable
9264       */
9265
9266       DPRINTF (("Check use: %s / %s",
9267                 exprNode_unparse (e), sRef_unparse (s)));
9268       
9269       exprNode_addUse (e, s);
9270      
9271       if (!context_inProtectVars ())
9272         {
9273           /*
9274           ** only report the deepest error
9275           */
9276           
9277           sRef errorRef = sRef_undefined;
9278           sRef lastRef  = sRef_undefined;
9279           bool deadRef = FALSE;
9280           bool unuseable = FALSE;
9281           bool errorMaybe = FALSE;
9282           
9283           while (sRef_isValid (s) && sRef_isKnown (s))
9284             {
9285               ynm readable = sRef_isReadable (s);
9286
9287               DPRINTF (("Readable: %s / %s",
9288                         sRef_unparseFull (s), ynm_unparse (readable)));
9289
9290               if (!(ynm_toBoolStrict (readable)))
9291                 {
9292                   if (ynm_isMaybe (readable))
9293                     {
9294                       lastRef = errorRef;
9295                       errorRef = s;
9296                       deadRef = sRef_isPossiblyDead (errorRef);
9297                       unuseable = sRef_isUnuseable (errorRef);
9298                       errorMaybe = TRUE;
9299                     }
9300                   else
9301                     {
9302                       lastRef = errorRef;
9303                       errorRef = s;
9304                       deadRef = sRef_isDead (errorRef);
9305                       unuseable = sRef_isUnuseable (errorRef);
9306                       errorMaybe = FALSE;
9307                     }
9308
9309                   if (!sRef_isPartial (s))
9310                     {
9311                       sRef_setDefined (s, fileloc_undefined);
9312                     }
9313                 }
9314
9315               s = sRef_getBaseSafe (s);
9316             } /* end while */
9317           
9318           if (sRef_isValid (errorRef)) 
9319             {
9320               if (sRef_isValid (lastRef) && sRef_isField (lastRef) 
9321                   && sRef_isPointer (errorRef))
9322                 {
9323                   errorRef = lastRef;
9324                 }
9325               
9326               if (deadRef)
9327                 {
9328                   if (sRef_isThroughArrayFetch (errorRef))
9329                     {
9330                       if (optgenerror 
9331                           (FLG_STRICTUSERELEASED,
9332                            message ("%q %q may be used after being released", 
9333                                     sRef_unparseKindNamePlain (errorRef),
9334                                     sRef_unparse (errorRef)),
9335                            loc))
9336                         {
9337                           sRef_showRefKilled (errorRef);
9338                           
9339                           if (sRef_isKept (errorRef))
9340                             {
9341                               sRef_clearAliasState (errorRef, loc);
9342                             }
9343                         }
9344                     }
9345                   else
9346                     {
9347                       DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9348
9349                       if (optgenerror
9350                           (FLG_USERELEASED,
9351                            message ("%q %q %qused after being released", 
9352                                     sRef_unparseKindNamePlain (errorRef),
9353                                     sRef_unparse (errorRef),
9354                                     cstring_makeLiteral (errorMaybe 
9355                                                          ? "may be " : "")),
9356                            loc))
9357                         {
9358                           sRef_showRefKilled (errorRef);
9359                           
9360                           if (sRef_isKept (errorRef))
9361                             {
9362                               sRef_clearAliasState (errorRef, loc);
9363                             }
9364                         }
9365                     }
9366                 }
9367               else if (unuseable)
9368                 {
9369                   if (optgenerror
9370                       (FLG_USEDEF,
9371                        message ("%q %q%qused in inconsistent state", 
9372                                 sRef_unparseKindName (errorRef),
9373                                 sRef_unparseOpt (errorRef),
9374                                 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9375                        loc))
9376                     {
9377                       sRef_showStateInconsistent (errorRef);
9378                     }
9379                 }
9380               else
9381                 {
9382                   DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
9383
9384                   voptgenerror 
9385                     (FLG_USEDEF,
9386                      message ("%q %q%qused before definition", 
9387                               sRef_unparseKindName (errorRef),
9388                               sRef_unparseOpt (errorRef),
9389                               cstring_makeLiteral (errorMaybe ? "may be " : "")),
9390                      loc);
9391                 }
9392               
9393               sRef_setDefined (errorRef, loc);
9394           
9395               if (sRef_isAddress (errorRef))
9396                 {
9397                   sRef_setDefined (sRef_getRootBase (errorRef), loc);
9398                 }
9399             } /* end is error */
9400         }
9401     }
9402
9403   setCodePoint ();
9404 }
9405
9406 static void
9407 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
9408 {
9409   if (exprNode_isDefined (e) && sRef_isKnown (s))
9410     {
9411       e->uses = sRefSet_insert (e->uses, s);
9412     }
9413 }
9414
9415 static void
9416 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9417 {
9418   if (exprNode_isDefined (e))
9419     {
9420       e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9421     }
9422 }
9423
9424 void
9425 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
9426 {
9427   sRef defines = sRef_undefined;
9428
9429   if (sRef_isValid (s) && !sRef_isNothing (s))
9430     {
9431       uentry ue = sRef_getBaseUentry (s);
9432
9433       if (uentry_isValid (ue))
9434         {
9435           uentry_setLset (ue);
9436         }
9437
9438       if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9439         {
9440           voptgenerror (FLG_USEDEF,
9441                         message ("Attempt to set unuseable storage: %q", 
9442                                  sRef_unparse (s)),
9443                         exprNode_loc (e));
9444         }
9445      
9446       if (sRef_isMeaningful (s))
9447         {
9448           
9449           if (sRef_isDead (s))
9450             {
9451               sRef base = sRef_getBaseSafe (s);
9452
9453               if (sRef_isValid (base) 
9454                   && sRef_isDead (base))
9455                 {
9456                   sRef_setPartial (s, exprNode_loc (e));
9457                 }
9458               
9459               defines = s; /* okay - modifies for only param */
9460             }
9461           else if (sRef_isPartial (s))
9462             {
9463               sRef eref = exprNode_getSref (e);
9464
9465               if (!sRef_isPartial (eref))
9466                 {
9467                   /*
9468                   ** should do something different here???
9469                   */
9470                   
9471                   sRef_setDefinedComplete (eref, exprNode_loc (e));               
9472                 }
9473               else
9474                 {
9475                   sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9476                 }
9477
9478               if (sRef_isMeaningful (eref))
9479                 {
9480                   defines = eref;
9481                 }
9482               else
9483                 {                
9484                   defines = s;
9485                 }
9486             }
9487           else if (sRef_isAllocated (s))
9488             {
9489               sRef eref = exprNode_getSref (e);
9490
9491               
9492               if (!sRef_isAllocated (eref))
9493                 {
9494                   sRef_setDefinedComplete (eref, exprNode_loc (e));
9495                 }
9496               else
9497                 {
9498                   sRef base = sRef_getBaseSafe (eref);
9499                   
9500                   if (sRef_isValid (base))
9501                     {
9502                       sRef_setPdefined (base, exprNode_loc (e)); 
9503                     }
9504                 }
9505
9506               defines = s;
9507             }
9508           else 
9509             {
9510               sRef_setDefinedNCComplete (s, exprNode_loc (e));
9511               defines = s;
9512             }
9513
9514         }
9515       else /* not meaningful...but still need to insert it */
9516         {
9517           defines = s;
9518         }
9519     }
9520
9521   if (exprNode_isDefined (e) && sRef_isValid (defines))
9522     {
9523       e->sets = sRefSet_insert (e->sets, defines); 
9524     }
9525 }
9526
9527 void
9528 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
9529 {
9530   if (sRef_isValid (s) && !sRef_isNothing (s))
9531     {
9532       uentry ue = sRef_getBaseUentry (s);
9533
9534       if (uentry_isValid (ue))
9535         {
9536           uentry_setLset (ue);
9537         }
9538
9539       if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9540         {
9541           voptgenerror (FLG_USEDEF,
9542                         message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9543                         exprNode_loc (e));
9544         }
9545       
9546       if (sRef_isMeaningful (s))
9547         {
9548           sRef_setDefinedComplete (s, exprNode_loc (e));
9549         }
9550       
9551       if (exprNode_isDefined (e))
9552         {
9553           e->msets = sRefSet_insert (e->msets, s);
9554         }
9555     }
9556 }
9557
9558 static void
9559 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9560 {
9561   checkAnyCall (fcn, cstring_undefined, params, args, 
9562                 FALSE, sRefSet_undefined, FALSE, 0);
9563 }
9564
9565 static void
9566 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current, 
9567              /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9568 {
9569   setCodePoint ();
9570   
9571   if (uentry_isYield (ucurrent))
9572     {
9573       sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9574       exprNode_checkSet (current, current->sref);
9575     }
9576   else 
9577     {
9578       if (uentry_isSefParam (ucurrent))
9579         {
9580           sRefSet sets = current->sets;
9581           sRef ref = exprNode_getSref (current);
9582
9583           if (sRef_isMacroParamRef (ref))
9584             {
9585               uentry ue = sRef_getUentry (ref);
9586
9587               if (!uentry_isSefParam (ue))
9588                 {
9589                   voptgenerror 
9590                     (FLG_SEFPARAMS,
9591                      message
9592                      ("Parameter %d to %s is declared sef, but "
9593                       "the argument is a macro parameter declared "
9594                       "without sef: %s",
9595                       argno, exprNode_unparse (fcn),
9596                       exprNode_unparse (current)),
9597                      exprNode_loc (current));
9598                 }
9599             }
9600
9601           if (!sRefSet_isEmpty (sets))
9602             {
9603               sRefSet reported = sRefSet_undefined;
9604               
9605               sRefSet_realElements (current->sets, el)
9606                 {
9607                   if (sRefSet_isSameNameMember (reported, el))
9608                     {
9609                       ; /* don't report again */
9610                     }
9611                   else
9612                     {
9613                       if (sRef_isUnconstrained (el))
9614                         {
9615                           voptgenerror 
9616                             (FLG_SEFUNSPEC,
9617                              message
9618                              ("Parameter %d to %s is declared sef, but "
9619                               "the argument calls unconstrained function %s "
9620                               "(no guarantee it will not modify something): %s",
9621                               argno, exprNode_unparse (fcn),
9622                               sRef_unconstrainedName (el),
9623                               exprNode_unparse (current)),
9624                              exprNode_loc (current));
9625                         }
9626                       else
9627                         {
9628                           voptgenerror 
9629                             (FLG_SEFPARAMS,
9630                              message
9631                              ("Parameter %d to %s is declared sef, but "
9632                               "the argument may modify %q: %s",
9633                               argno, exprNode_unparse (fcn),
9634                               sRef_unparse (el),
9635                               exprNode_unparse (current)),
9636                              exprNode_loc (current));
9637                         }
9638                     } 
9639                 } end_sRefSet_realElements;
9640             }
9641         }
9642       
9643       checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9644       exprNode_mergeUSs (fcn, current);
9645     }
9646 }
9647
9648 static void
9649   checkAnyCall (/*@dependent@*/ exprNode fcn, 
9650                 /*@dependent@*/ cstring fname,
9651                 uentryList pn, 
9652                 exprNodeList args, 
9653                 bool hasMods, sRefSet mods,
9654                 bool isSpec,
9655                 int specialArgs)
9656 {
9657   int paramno = 0;
9658   int nargs = exprNodeList_size (args);
9659
9660   setCodePoint ();
9661
9662   /*
9663   ** concat all args ud's to f, add each arg sref as a use unless
9664   ** it was specified as "out", in which case it is a def.
9665   */
9666   
9667   uentryList_reset (pn);
9668   
9669   /*
9670   ** aliasing checks:
9671   **
9672   **    if paramn is only or unique, no other arg may alias argn
9673   */
9674   
9675   exprNodeList_elements (args, current) 
9676     {
9677       paramno++;
9678       
9679       if (exprNode_isDefined (current)) 
9680         {
9681           if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn))) 
9682             {
9683               uentry ucurrent = uentryList_current (pn);
9684               
9685               if (specialArgs == 0 
9686                   || (paramno < specialArgs))
9687                 {
9688                   checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
9689
9690                   if (context_maybeSet (FLG_ALIASUNIQUE))
9691                     {
9692                       if (uentry_isOnly (ucurrent)
9693                           || uentry_isUnique (ucurrent))
9694                         {
9695                           checkUniqueParams (fcn, current, args,
9696                                              paramno, ucurrent);
9697                         }
9698                     }
9699                 } 
9700             }
9701           else /* uentry is undefined */
9702             {
9703               if (specialArgs == 0)
9704                 {
9705                   exprNode_checkUseParam (current);
9706                 }
9707
9708               exprNode_mergeUSs (fcn, current);
9709             }   
9710         }
9711       uentryList_advanceSafe (pn);
9712     } end_exprNodeList_elements;
9713   
9714   if (hasMods)
9715     {
9716       setCodePoint ();
9717
9718       sRefSet_allElements (mods, s)
9719         {
9720           sRef fb;
9721           sRef rb = sRef_getRootBase (s);
9722           
9723           if (sRef_isFileOrGlobalScope (rb))
9724             {
9725               context_usedGlobal (rb);
9726             }
9727           
9728           fb = sRef_fixBaseParam (s, args);
9729           
9730           if (!sRef_isMacroParamRef (fb))
9731             {
9732               if (sRef_isNothing (fb))
9733                 {
9734                   ;
9735                 }
9736               else
9737                 {
9738                   if (sRef_isValid (fb))
9739                     {
9740                       uentry ue = sRef_getBaseUentry (s);
9741                       
9742                       if (uentry_isValid (ue))
9743                         {
9744                           uentry_setLset (ue);
9745                         }
9746                     }
9747                   
9748                   fcn->sets = sRefSet_insert (fcn->sets, fb);
9749                 }
9750             }
9751           sRef_clearDerivedComplete (s); 
9752         } end_sRefSet_allElements;
9753       
9754       setCodePoint ();
9755     }
9756   else
9757     {
9758       if (context_hasMods ())
9759         {
9760           if (context_maybeSet (FLG_MODUNCON))
9761             {
9762               voptgenerror
9763                 (FLG_MODUNCON,
9764                  message ("Undetected modification possible "
9765                           "from call to unconstrained function %s: %s", 
9766                           fname,
9767                           exprNode_unparse (fcn)),
9768                  exprNode_loc (fcn));
9769             }
9770         }
9771       else
9772         {
9773           if (context_maybeSet (FLG_MODUNCONNOMODS)
9774               && !(context_inIterDef () || context_inIterEnd ()))
9775             {
9776               voptgenerror
9777                 (FLG_MODUNCONNOMODS,
9778                  message ("Undetected modification possible "
9779                           "from call to unconstrained function %s: %s", 
9780                           fname,
9781                           exprNode_unparse (fcn)),
9782                  exprNode_loc (fcn));
9783             }
9784         }
9785
9786       exprNode_checkSetAny (fcn, fname);
9787     }
9788 }
9789
9790 void exprNode_checkUseParam (exprNode current)
9791 {
9792   if (exprNode_isDefined (current))
9793     {
9794       exprNode_checkUse (current, current->sref, current->loc);
9795     }
9796 }
9797
9798 static ctype
9799   checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
9800                  /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9801                  lltok op)
9802 {
9803   ctype ret = tr1;
9804   
9805   if (!ctype_match (tr1, tr2))
9806     {
9807       if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
9808           (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
9809         {
9810           ;
9811         }
9812       else
9813         {
9814           (void) gentypeerror 
9815             (tr1, e1, tr2, e2,
9816              message ("Incompatible types for %s (%s, %s): %s %s %s",
9817                       lltok_unparse (op),
9818                       ctype_unparse (te1),
9819                       ctype_unparse (te2),
9820                       exprNode_unparse (e1), lltok_unparse (op), 
9821                       exprNode_unparse (e2)),
9822              e1->loc);
9823         }
9824       ret = ctype_unknown;
9825     }
9826   else
9827     {
9828       if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
9829         {
9830           ret = ctype_resolveNumerics (tr1, tr2);
9831         }
9832       else if (!context_msgStrictOps ()) 
9833         {
9834                   if (ctype_isPointer (tr1))
9835             {
9836               if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
9837                 {
9838                   ret = ctype_int;
9839                 }
9840               else if (ctype_isInt (tr2))
9841                 {
9842                   ret = te1;
9843                 }
9844               else
9845                 {
9846                   ret = ctype_unknown;
9847                 }
9848             }
9849           else if (ctype_isPointer (tr2))
9850             {
9851               if (ctype_isPointer (tr1))
9852                 {
9853                   ret = ctype_int;
9854                 }
9855               else if (ctype_isInt (tr1))
9856                 {
9857                   ret = te2;
9858                 }
9859               else
9860                 {
9861                   ret = ctype_unknown; 
9862                 }
9863             }
9864           else
9865             {
9866               ret = ctype_resolveNumerics (tr1, tr2);
9867             }
9868         }
9869       else
9870         {
9871           int opid = lltok_getTok (op);
9872           bool comparop = (opid == EQ_OP || opid == NE_OP 
9873                            || opid == TLT || opid == TGT
9874                            || opid == LE_OP || opid == GE_OP);
9875           
9876           if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
9877             {
9878               if (comparop
9879                   && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
9880                       || (ctype_isBool (tr1) && ctype_isBool (tr2))
9881                       || (ctype_isChar (tr1) && ctype_isChar (tr2))))
9882                 {
9883                   ; /* no error */
9884                 }
9885               else
9886                 {
9887                   if (ctype_sameName (te1, te2))
9888                     {
9889                       voptgenerror
9890                         (FLG_STRICTOPS,
9891                          message ("Operands of %s are non-numeric (%t): %s %s %s",
9892                                   lltok_unparse (op), te1, 
9893                                   exprNode_unparse (e1), lltok_unparse (op), 
9894                                   exprNode_unparse (e2)),
9895                          e1->loc);
9896                     }
9897                   else
9898                     {
9899                       voptgenerror
9900                         (FLG_STRICTOPS,
9901                          message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
9902                                   lltok_unparse (op), te1, te2, 
9903                                   exprNode_unparse (e1), lltok_unparse (op),
9904                                   exprNode_unparse (e2)),
9905                          e1->loc);
9906                     }
9907                 }
9908             }
9909           else if (!ctype_isNumeric (tr1))
9910             {
9911               voptgenerror
9912                 (FLG_STRICTOPS,
9913                  message ("Right operand of %s is non-numeric (%t): %s %s %s",
9914                           lltok_unparse (op), te1, 
9915                           exprNode_unparse (e1), lltok_unparse (op), 
9916                           exprNode_unparse (e2)),
9917                  e1->loc);
9918             }
9919           else 
9920             {
9921               if (!ctype_isNumeric (tr2))
9922                 {
9923                   voptgenerror
9924                     (FLG_STRICTOPS,
9925                      message ("Left operand of %s is non-numeric (%t): %s %s %s",
9926                               lltok_unparse (op), te2, 
9927                               exprNode_unparse (e1), lltok_unparse (op), 
9928                               exprNode_unparse (e2)),
9929                      e2->loc);
9930                 }
9931             }
9932           
9933           ret = ctype_unknown;
9934         }
9935     }
9936
9937   return ret;
9938 }
9939
9940 static void
9941 abstractOpError (ctype tr1, ctype tr2, lltok op, 
9942                  /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, 
9943                  fileloc loc1, fileloc loc2)
9944 {
9945   if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
9946     {
9947       if (ctype_match (tr1, tr2))
9948         {
9949           voptgenerror
9950             (FLG_ABSTRACT,
9951              message ("Operands of %s are abstract type (%t): %s %s %s",
9952                       lltok_unparse (op), tr1, 
9953                       exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9954              loc1);
9955         }
9956       else
9957         {
9958           voptgenerror 
9959             (FLG_ABSTRACT,
9960              message ("Operands of %s are abstract types (%t, %t): %s %s %s",
9961                       lltok_unparse (op), tr1, tr2, 
9962                       exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9963              loc1);
9964         }
9965     }
9966   else if (ctype_isRealAbstract (tr1))
9967     {
9968       voptgenerror
9969         (FLG_ABSTRACT,
9970          message ("Left operand of %s is abstract type (%t): %s %s %s",
9971                   lltok_unparse (op), tr1, 
9972                   exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9973          loc1);
9974     }
9975   else 
9976     {
9977       if (ctype_isRealAbstract (tr2))
9978         {
9979           voptgenerror
9980             (FLG_ABSTRACT,
9981              message ("Right operand of %s is abstract type (%t): %s %s %s",
9982                       lltok_unparse (op), tr2, 
9983                       exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9984              loc2);
9985         }
9986     }
9987 }
9988
9989 /*
9990 ** e1 <= e2
9991 **
9992 ** requies e1 and e2 and not error exprNode's.
9993 **
9994 ** Checks:
9995 **
9996 **    If e1 is a component of an abstract type, and e2 is mutable and client-visible, 
9997 **    the rep of the abstract type is exposed.
9998 **
9999 ** The order is very important:
10000 **
10001 **    check rep expose (move into check transfer)
10002 **    check transfer
10003 **    setup aliases
10004 */
10005
10006 /*
10007 ** This isn't really a sensible procedure, but the indententation
10008 ** was getting too deep.
10009 */
10010
10011 static void
10012 checkOneRepExpose (sRef ysr, sRef base, 
10013                    /*@notnull@*/ exprNode e1, 
10014                    /*@notnull@*/ exprNode e2, ctype ct,
10015                    sRef s2b)
10016 {
10017   if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr) 
10018         || sRef_isOwned (ysr) 
10019         || sRef_isExposed (ysr)))
10020     {
10021       if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10022           && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10023
10024         {
10025           if (sRef_isIReference (ysr))
10026             {
10027               if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10028                 {
10029                   voptgenerror 
10030                     (FLG_ASSIGNEXPOSE,
10031                      message
10032                      ("Assignment of mutable component of parameter %q "
10033                       "to component of abstract "
10034                       "type %s exposes rep: %s = %s",
10035                       sRef_unparse (base),
10036                       ctype_unparse (ct),
10037                       exprNode_unparse (e1), exprNode_unparse (e2)),
10038                      e1->loc);
10039                 }
10040               else
10041                 {
10042                   voptgenerror 
10043                     (FLG_ASSIGNEXPOSE,
10044                      message
10045                      ("Assignment of mutable component of parameter %q "
10046                       "(through alias %q) to component of abstract "
10047                       "type %s exposes rep: %s = %s",
10048                       sRef_unparse (base),
10049                       sRef_unparse (e2->sref),
10050                       ctype_unparse (ct),
10051                       exprNode_unparse (e1), exprNode_unparse (e2)),
10052                      e1->loc);
10053                 }
10054             }
10055           else
10056             {
10057               if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10058                 {
10059                   voptgenerror 
10060                     (FLG_ASSIGNEXPOSE,
10061                      message ("Assignment of mutable parameter %q "
10062                               "to component of abstract type %s "
10063                               "exposes rep: %s = %s",
10064                               sRef_unparse (base),
10065                               ctype_unparse (ct),
10066                               exprNode_unparse (e1), 
10067                               exprNode_unparse (e2)),
10068                      e1->loc);
10069                 }
10070               else
10071                 {
10072                   voptgenerror 
10073                     (FLG_ASSIGNEXPOSE,
10074                      message ("Assignment of mutable parameter %q "
10075                               "(through alias %q) to "
10076                               "component of abstract type %s exposes "
10077                               "rep: %s = %s",
10078                               sRef_unparse (base),
10079                               sRef_unparse (e2->sref),
10080                               ctype_unparse (ct),
10081                               exprNode_unparse (e1), 
10082                               exprNode_unparse (e2)),
10083                      e1->loc);
10084                 }
10085             }
10086         }
10087       
10088       if (sRef_isFileOrGlobalScope (s2b))
10089         {
10090           if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10091             {
10092               voptgenerror 
10093                 (FLG_REPEXPOSE,
10094                  message ("Assignment of global %q "
10095                           "to component of "
10096                           "abstract type %s exposes rep: %s = %s",
10097                           sRef_unparse (base),
10098                           ctype_unparse (ct),
10099                           exprNode_unparse (e1), exprNode_unparse (e2)),
10100                  e1->loc);
10101             }
10102           else
10103             {
10104               voptgenerror 
10105                 (FLG_REPEXPOSE,
10106                  message ("Assignment of global %q (through alias %q) "
10107                           "to component of "
10108                           "abstract type %s exposes rep: %s = %s",
10109                           sRef_unparse (base),
10110                           sRef_unparse (e2->sref),
10111                           ctype_unparse (ct),
10112                           exprNode_unparse (e1), exprNode_unparse (e2)),
10113                  e1->loc);
10114             }
10115         }
10116     }
10117 }
10118
10119 static void
10120 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10121 {
10122   if (ctype_isRealFunction (exprNode_getType (e1))
10123       && !ctype_isRealPointer (exprNode_getType (e1)))
10124     {
10125       voptgenerror 
10126         (FLG_TYPE,
10127          message ("Invalid left-hand side of assignment (function type %s): %s",
10128                   ctype_unparse (exprNode_getType (e1)),
10129                   exprNode_unparse (e1)),
10130          e1->loc);
10131     }
10132
10133   if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10134     {
10135       ctype t2 = exprNode_getType (e2);
10136       sRef sr = sRef_getRootBase (e1->sref);
10137       ctype ct = sRef_getType (sr);
10138
10139       if (ctype_isAbstract (t2) 
10140           && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10141         {
10142           /* it is immutable, okay to reference */
10143           goto donerepexpose;
10144         }
10145
10146       if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10147         {
10148           sRef s2b = sRef_getRootBase (e2->sref);
10149           sRef s1 = e1->sref;
10150           sRef s1b = sRef_getRootBase (s1);
10151           sRefSet aliases;
10152
10153           aliases = usymtab_canAlias (e2->sref);
10154           
10155           if (!sRef_similar (s2b, s1b) 
10156               && !sRef_isExposed (s1)
10157               && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10158             {
10159               if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b) 
10160                   && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10161                   && !sRef_isExposed (s2b))
10162                 {
10163                   if (sRef_isIReference (e2->sref))
10164                     {
10165                       voptgenerror 
10166                         (FLG_ASSIGNEXPOSE,
10167                          message 
10168                          ("Assignment of mutable component of parameter %q "
10169                           "to component of abstract type %s exposes rep: %s = %s",
10170                           sRef_unparse (s2b),
10171                           ctype_unparse (ct),
10172                           exprNode_unparse (e1), exprNode_unparse (e2)),
10173                          e1->loc);
10174                     }
10175                   else
10176                     {
10177                       voptgenerror 
10178                         (FLG_ASSIGNEXPOSE,
10179                          message ("Assignment of mutable parameter %q to "
10180                                   "component of abstract type %s exposes rep: %s = %s",
10181                                   sRef_unparse (s2b),
10182                                   ctype_unparse (ct),
10183                                   exprNode_unparse (e1), exprNode_unparse (e2)),
10184                          e1->loc);
10185                     }
10186                 }
10187
10188               if (sRef_isFileOrGlobalScope (s2b))
10189                 {
10190                   voptgenerror
10191                     (FLG_ASSIGNEXPOSE,
10192                      message ("Assignment of global %q to component of "
10193                               "abstract type %s exposes rep: %s = %s",
10194                               sRef_unparse (s2b),
10195                               ctype_unparse (ct),
10196                               exprNode_unparse (e1), exprNode_unparse (e2)),
10197                      e1->loc);
10198                 }
10199               
10200               sRefSet_realElements (aliases, ysr)
10201                 {
10202                   sRef base = sRef_getRootBase (ysr);
10203                   
10204                   if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10205                       || sRef_sameName (base, s1b))
10206                     {
10207                      ; /* error already reported or same sref */
10208                     }
10209                   else
10210                     {
10211                       checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10212                     }
10213                 } end_sRefSet_realElements;
10214             }
10215           sRefSet_free (aliases);
10216         }
10217     }
10218
10219  donerepexpose:
10220
10221   /*
10222   ** function variables don't really work...
10223   */
10224
10225   if (!ctype_isFunction (ctype_realType (e2->typ)))
10226     {
10227       if (isInit)
10228         {
10229             DPRINTF (("Check init: %s / %s",
10230                       exprNode_unparse (e1), exprNode_unparse (e2)));
10231           checkInitTransfer (e1, e2); 
10232         }
10233       else
10234         {
10235           checkAssignTransfer (e1, e2); 
10236         }
10237     }
10238   else
10239     {
10240       sRef fref = e2->sref;
10241
10242       sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10243       sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10244
10245             /* Need to typecheck the annotation on the parameters */
10246       
10247       if (ctype_isRealFunction (e1->typ)) {
10248         uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10249         uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10250
10251         if (!uentryList_isMissingParams (e1p)
10252             && !uentryList_isMissingParams (e2p)
10253             && uentryList_size (e1p) > 0) {
10254           if (uentryList_size (e1p) == uentryList_size (e2p)) {
10255             int n = 0;
10256             
10257             uentryList_elements (e1p, el1) {
10258               uentry el2;
10259
10260               el2 = uentryList_getN (e2p, n);
10261               n++;
10262               uentry_checkMatchParam (el1, el2, n, e2);
10263             } end_uentryList_elements;
10264           }
10265         }
10266       }
10267     }
10268
10269   if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10270     {
10271        ;
10272     }
10273   else
10274     {
10275       DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10276       updateAliases (e1, e2); 
10277     }
10278 }
10279
10280 static void 
10281 checkMacroParen (exprNode e)
10282 {
10283   if (exprNode_isError (e) || e->kind == XPR_CAST)
10284     {
10285      ;
10286     }
10287   else 
10288     {
10289       if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10290         {
10291           voptgenerror 
10292             (FLG_MACROPARENS,
10293              message ("Macro parameter used without parentheses: %s", 
10294                       exprNode_unparse (e)),
10295              e->loc);
10296         }
10297     }
10298 }
10299
10300 static void
10301 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10302 {
10303   if (isnull)
10304     {
10305       e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10306     }
10307   else
10308     {
10309       e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10310     }
10311 }
10312
10313 /*
10314 ** e1 <= e2
10315 **
10316 ** if e2 is a parameter or global derived location which
10317 ** can be modified (that is, e2 is a mutable abstract type,
10318 ** or a derived pointer), then e1 can alias e2.
10319 **
10320 ** e1 can alias everything which e2 can alias.
10321 **
10322 ** Also, if e1 is guarded, remove from guard sets!
10323 */
10324
10325 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10326 {
10327   if (!context_inProtectVars ())
10328     {
10329       /*
10330       ** depends on types of e1 and e2
10331       */
10332       
10333       sRef s1 = e1->sref;
10334       sRef s2 = e2->sref;
10335       ctype t1 = exprNode_getType (e1);
10336       
10337       /* handle pointer sRefs, record fields, arrays, etc... */
10338       
10339       if (!ctype_isRealSU (t1))
10340         {
10341           DPRINTF (("Copying real! %s", ctype_unparse (t1)));
10342           sRef_copyRealDerivedComplete (s1, s2);
10343         }
10344       else
10345         {
10346           /*
10347           ** Fields should alias
10348           */
10349
10350           DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10351         }
10352
10353       if (ctype_isMutable (t1) && sRef_isKnown (s1))
10354         {
10355           usymtab_clearAlias (s1);
10356           usymtab_addMustAlias (s1, s2); 
10357           DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10358         }
10359       else
10360         {
10361           DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
10362         }
10363
10364       if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10365         {
10366           usymtab_unguard (s1);
10367         }
10368     }
10369 }
10370
10371 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10372 {
10373   if (exprNode_isDefined (e))
10374     {
10375       e->loc = fileloc_update (e->loc, loc);
10376     }
10377   else
10378     {
10379       e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10380     }
10381
10382   return (e);
10383 }
10384
10385 static void checkUniqueParams (exprNode fcn,
10386                                /*@notnull@*/ exprNode current, 
10387                                exprNodeList args, 
10388                                int paramno, uentry ucurrent)
10389 {
10390   int iparamno = 0;
10391   sRef thisref = exprNode_getSref (current);
10392   
10393   /*
10394   ** Check if any argument could match this argument.
10395   */
10396   
10397   exprNodeList_elements (args, icurrent) 
10398     {
10399       iparamno++;
10400       
10401       if (iparamno != paramno)
10402         {
10403           sRef sr = exprNode_getSref (icurrent);
10404           
10405           if (sRef_similarRelaxed (thisref, sr))
10406             {
10407               if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10408                 {
10409                   voptgenerror 
10410                     (FLG_ALIASUNIQUE,
10411                      message
10412                      ("Parameter %d (%s) to function %s is declared %s but "
10413                       "is aliased by parameter %d (%s)",
10414                       paramno, 
10415                       exprNode_unparse (current),
10416                       exprNode_unparse (fcn),
10417                       alkind_unparse (uentry_getAliasKind (ucurrent)),
10418                       iparamno, exprNode_unparse (icurrent)),
10419                      current->loc);
10420                 }
10421             }
10422           else
10423             {
10424               sRefSet aliases = usymtab_canAlias (sr);
10425
10426               sRefSet_allElements (aliases, asr)
10427                 {
10428                   if (ctype_isUnknown (sRef_getType (thisref)))
10429                     {
10430                       sRef_setType (thisref, uentry_getType (ucurrent));
10431                     }
10432                   
10433                   if (sRef_similarRelaxed (thisref, asr)) 
10434                     {
10435                       if (sRef_isExternal (asr))  
10436                         {
10437                           if (sRef_isLocalState (thisref))
10438                             {
10439                               ; /* okay */
10440                             }
10441                           else
10442                             {
10443                               sRef base = sRef_getRootBase (asr);
10444                               
10445                               if (!sRef_similar (sRef_getBase (asr), thisref)) 
10446                                 {
10447                                   if (sRef_isUnique (base) || sRef_isOnly (base)
10448                                       || sRef_isKept (base)
10449                                       || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10450                                       || (sRef_isAddress (thisref) 
10451                                           && sRef_isLocalVar (sRef_getRootBase (thisref))))
10452                                     {
10453                                       ; /* okay, no error */
10454                                     }
10455                                   else
10456                                     {
10457                                       voptgenerror 
10458                                         (FLG_MAYALIASUNIQUE,
10459                                          message
10460                                          ("Parameter %d (%s) to function %s is declared %s but "
10461                                           "may be aliased externally by parameter %d (%s)",
10462                                           paramno, 
10463                                           exprNode_unparse (current),
10464                                           exprNode_unparse (fcn),
10465                                           alkind_unparse (uentry_getAliasKind (ucurrent)),
10466                                           iparamno, exprNode_unparse (icurrent)),
10467                                          current->loc);
10468                                     }
10469                                 }
10470                             }
10471                         }
10472                       else
10473                         {
10474                           voptgenerror 
10475                             (FLG_ALIASUNIQUE,
10476                              message
10477                              ("Parameter %d (%s) to function %s is declared %s but "
10478                               "is aliased externally by parameter %d (%s) through "
10479                               "alias %q",
10480                               paramno, 
10481                               exprNode_unparse (current),
10482                               exprNode_unparse (fcn),
10483                               alkind_unparse (uentry_getAliasKind (ucurrent)),
10484                               iparamno, exprNode_unparse (icurrent),
10485                               sRef_unparse (asr)),
10486                              current->loc);
10487                         }
10488                     }
10489                 } end_sRefSet_allElements;
10490               sRefSet_free (aliases);
10491             }
10492         }
10493     } end_exprNodeList_elements;
10494 }
10495
10496 long exprNode_getLongValue (exprNode e) {
10497   long value;
10498
10499   if (exprNode_hasValue (e) 
10500       && multiVal_isInt (exprNode_getValue (e)))
10501     {
10502       value = multiVal_forceInt (exprNode_getValue (e));
10503     }
10504   else
10505     {
10506       value = 0;
10507     }
10508   
10509   return value;
10510 }
10511
10512 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
10513 {
10514   if (exprNode_isDefined (p_e) )
10515     return ( p_e->loc );
10516   else
10517     return fileloc_undefined;
10518 }
10519
10520 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
10521 {
10522   /*
10523   ** Returns the location of the sequence point following e.
10524   **
10525   ** Only works for statements (for now).
10526   */
10527
10528   if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10529     lltok t = exprData_getUopTok (e->edata);
10530     return fileloc_copy(lltok_getLoc (t));
10531   } else {
10532     //drl possible problem : warning fix
10533     //    llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
10534     return fileloc_undefined;
10535   }
10536  }
10537
10538 exprNode exprNode_createNew(ctype c)
10539 {
10540   exprNode ret;
10541
10542   ret = exprNode_createPlain (c);
10543
10544   return ret;
10545 }
This page took 0.892137 seconds and 5 git commands to generate.