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