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