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