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