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