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