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