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