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