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